Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. if you hate writing and trying to test multithreaded code raise your hand

if you hate writing and trying to test multithreaded code raise your hand

Scheduled Pinned Locked Moved The Lounge
14 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H honey the codewitch

    I'm implementing thread safety on a large class after the fact. i hate this. but it has to be done. also Microsoft, what the hell. you didn't put versioning on your dictionary enumerators** ** means when the dictionary is changed the enumerator won't throw like it's supposed to.

    When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

    Greg UtasG Offline
    Greg UtasG Offline
    Greg Utas
    wrote on last edited by
    #2

    I could write an entire article p() and v() Considered Harmful. Just as the use of goto should usually be restricted to the compiler, thread safety should usually be restricted to a few places by using cooperative scheduling (running work to completion). Willy-nilly preemptive scheduling is an abomination that causes artificial complexity, polluting the code with stuff that has nothing to do with the specifications.

    <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
    <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

    H 1 Reply Last reply
    0
    • Greg UtasG Greg Utas

      I could write an entire article p() and v() Considered Harmful. Just as the use of goto should usually be restricted to the compiler, thread safety should usually be restricted to a few places by using cooperative scheduling (running work to completion). Willy-nilly preemptive scheduling is an abomination that causes artificial complexity, polluting the code with stuff that has nothing to do with the specifications.

      H Offline
      H Offline
      honey the codewitch
      wrote on last edited by
      #3

      so you are a fan of cooperative threading? I can see the appeal, but it does very little when it comes to utilizing more than one CPU/core. At that point, you're going to have concurrency issues save some higher level task functionality included as part of the CPU architecture. Besides, i think cooperative multithreading is better handled using coroutines. That way the code design in clearer. In c#, coroutines are built using the yield statement.

      When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

      Greg UtasG 1 Reply Last reply
      0
      • H honey the codewitch

        so you are a fan of cooperative threading? I can see the appeal, but it does very little when it comes to utilizing more than one CPU/core. At that point, you're going to have concurrency issues save some higher level task functionality included as part of the CPU architecture. Besides, i think cooperative multithreading is better handled using coroutines. That way the code design in clearer. In c#, coroutines are built using the yield statement.

        When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

        Greg UtasG Offline
        Greg UtasG Offline
        Greg Utas
        wrote on last edited by
        #4

        Yes, I'm a big fan of cooperative threading. I haven't worked in C#, but I'd guess that yield() does the same thing as what I call Pause() in my code. Symmetric multiprocessing (SMP) is another abomination because it reintroduces the need for all this thread safety nonsense. It is lamentable that Intel ran contests on how to adapt software to these platforms. SMP is a case of the hardware team having fun at the expense of the software team, which we all know is backwards from how things should be! I also look at it this way, that there are only three good numbers: 0, 1, and infinity. So if I need more than one core, will 2, 4, or 8 always be enough? The general solution is to design software that runs in a distributed (networked) manner. This adds artificial complexity of its own, but it's the truly scalable solution and is unavoidable if you need an arbitrary amount of horsepower. The resulting software can also run on an SMP platform by dividing the shared memory so that each core has its own sandbox, with shared memory perhaps being used only for efficient interprocessor messaging.

        <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
        <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

        H 1 Reply Last reply
        0
        • Greg UtasG Greg Utas

          Yes, I'm a big fan of cooperative threading. I haven't worked in C#, but I'd guess that yield() does the same thing as what I call Pause() in my code. Symmetric multiprocessing (SMP) is another abomination because it reintroduces the need for all this thread safety nonsense. It is lamentable that Intel ran contests on how to adapt software to these platforms. SMP is a case of the hardware team having fun at the expense of the software team, which we all know is backwards from how things should be! I also look at it this way, that there are only three good numbers: 0, 1, and infinity. So if I need more than one core, will 2, 4, or 8 always be enough? The general solution is to design software that runs in a distributed (networked) manner. This adds artificial complexity of its own, but it's the truly scalable solution and is unavoidable if you need an arbitrary amount of horsepower. The resulting software can also run on an SMP platform by dividing the shared memory so that each core has its own sandbox, with shared memory perhaps being used only for efficient interprocessor messaging.

          H Offline
          H Offline
          honey the codewitch
          wrote on last edited by
          #5

          Greg Utas wrote:

          Yes, I'm a big fan of cooperative threading. I haven't worked in C#, but I'd guess that yield() does the same thing as what I call Pause() in my code.

          Probably "inside out" of what you're thinking. Assuming you call Pause() while inside a loop or something to yield time. yield however, is entirely different. It builds state machines for you to break apart the routine. Hence

          IEnumerable Test() {
          yield return "dog";
          yield return "cat";
          yield return "mouse";
          }
          ...
          foreach(var item in Test())
          Console.WriteLine(item);

          yields dog cat mouse each time it encounters a yield return it returns from the function. The next time the function is called essentially it will start after that yield return statement at the next line. This voodoo is accomplished using a state machine the compiler builds for you. So each time the routine is called, it knows what state it's in and can execute the next instruction. So in your cooperative multithreading code. you'd just loop over whatever you needed to loop over, and time is returned to your function because the yield return dropped you out of the function in the "middle of the call" it's a lot easier to use than to explain, but it helps if you have familiarity with the concept of a coroutine first.

          When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

          Greg UtasG 1 Reply Last reply
          0
          • H honey the codewitch

            Greg Utas wrote:

            Yes, I'm a big fan of cooperative threading. I haven't worked in C#, but I'd guess that yield() does the same thing as what I call Pause() in my code.

            Probably "inside out" of what you're thinking. Assuming you call Pause() while inside a loop or something to yield time. yield however, is entirely different. It builds state machines for you to break apart the routine. Hence

            IEnumerable Test() {
            yield return "dog";
            yield return "cat";
            yield return "mouse";
            }
            ...
            foreach(var item in Test())
            Console.WriteLine(item);

            yields dog cat mouse each time it encounters a yield return it returns from the function. The next time the function is called essentially it will start after that yield return statement at the next line. This voodoo is accomplished using a state machine the compiler builds for you. So each time the routine is called, it knows what state it's in and can execute the next instruction. So in your cooperative multithreading code. you'd just loop over whatever you needed to loop over, and time is returned to your function because the yield return dropped you out of the function in the "middle of the call" it's a lot easier to use than to explain, but it helps if you have familiarity with the concept of a coroutine first.

            When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

            Greg UtasG Offline
            Greg UtasG Offline
            Greg Utas
            wrote on last edited by
            #6

            Interesting and not what I expected. Many folks couldn't be bothered to write a state machine, so we get blocking RPCs. And why do we get an hourglass or little spinning wheel on the screen? It's because some wanker couldn't be bothered to write a state machine! So I'm curious as to what kind of state machine this generates. It picks up where it left off, but a serious state machine handles any input that could arrive. I'm guessing that this blocks, which is OK sometimes (guaranteed low latency) but not others (waiting for a reply from another processor). It's the latter case that can put a little spinning wheel on the screen for an unbecoming length of time, which is loathsome.

            <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
            <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

            H 1 Reply Last reply
            0
            • Greg UtasG Greg Utas

              Interesting and not what I expected. Many folks couldn't be bothered to write a state machine, so we get blocking RPCs. And why do we get an hourglass or little spinning wheel on the screen? It's because some wanker couldn't be bothered to write a state machine! So I'm curious as to what kind of state machine this generates. It picks up where it left off, but a serious state machine handles any input that could arrive. I'm guessing that this blocks, which is OK sometimes (guaranteed low latency) but not others (waiting for a reply from another processor). It's the latter case that can put a little spinning wheel on the screen for an unbecoming length of time, which is loathsome.

              H Offline
              H Offline
              honey the codewitch
              wrote on last edited by
              #7

              It does block but there's another mechanism that does what you're talking about (not blocking) It's called awaitable methods and basically they let you return pending a callback . for I/O bound operations, this is particularly desirable, but it's also helpful for CPU bound threads. The compiler builds a state machine so you can do like async bool StartJob() { var result = await DoLongRunningThing(); // method "exits" here, //pending a callback at which point it picks up here } sorry it's a bit contrived, but it's really easy once you get the hang of it.

              When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

              Greg UtasG 1 Reply Last reply
              0
              • H honey the codewitch

                It does block but there's another mechanism that does what you're talking about (not blocking) It's called awaitable methods and basically they let you return pending a callback . for I/O bound operations, this is particularly desirable, but it's also helpful for CPU bound threads. The compiler builds a state machine so you can do like async bool StartJob() { var result = await DoLongRunningThing(); // method "exits" here, //pending a callback at which point it picks up here } sorry it's a bit contrived, but it's really easy once you get the hang of it.

                When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                Greg UtasG Offline
                Greg UtasG Offline
                Greg Utas
                wrote on last edited by
                #8

                And I thought that C++ was a kitchen-sink language! That said, good on them that they allow other inputs. Not that I care for RPCs. But if this is in the thread's entry function, it's not much different than accepting any message that could arrive, so it looks like the kind of thing I'd aim for.

                <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
                <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

                H 1 Reply Last reply
                0
                • Greg UtasG Greg Utas

                  And I thought that C++ was a kitchen-sink language! That said, good on them that they allow other inputs. Not that I care for RPCs. But if this is in the thread's entry function, it's not much different than accepting any message that could arrive, so it looks like the kind of thing I'd aim for.

                  H Offline
                  H Offline
                  honey the codewitch
                  wrote on last edited by
                  #9

                  the var declaration is actually typed. The compiler picks up the type implicitly from the return value of the function it was initialized using; if I do: var i = 0; i will be an int. so i can't later do i = "foo"; // compile error it's helpful due to lack of typedefs for example.

                  When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                  1 Reply Last reply
                  0
                  • H honey the codewitch

                    I'm implementing thread safety on a large class after the fact. i hate this. but it has to be done. also Microsoft, what the hell. you didn't put versioning on your dictionary enumerators** ** means when the dictionary is changed the enumerator won't throw like it's supposed to.

                    When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                    N Offline
                    N Offline
                    Nand32
                    wrote on last edited by
                    #10

                    Port everything to Javascript (node) :-D Problem solved. (just kidding)

                    1 Reply Last reply
                    0
                    • H honey the codewitch

                      I'm implementing thread safety on a large class after the fact. i hate this. but it has to be done. also Microsoft, what the hell. you didn't put versioning on your dictionary enumerators** ** means when the dictionary is changed the enumerator won't throw like it's supposed to.

                      When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                      M Offline
                      M Offline
                      Munchies_Matt
                      wrote on last edited by
                      #11

                      Ouch, that is going to be a mess. It isnt that threads are difficult, it is that they are a fundamental part of the architecture, and need to go in first, not at the end, as a bodge. Probably better to redesign the whole thing.

                      H 1 Reply Last reply
                      0
                      • M Munchies_Matt

                        Ouch, that is going to be a mess. It isnt that threads are difficult, it is that they are a fundamental part of the architecture, and need to go in first, not at the end, as a bodge. Probably better to redesign the whole thing.

                        H Offline
                        H Offline
                        honey the codewitch
                        wrote on last edited by
                        #12

                        it was fine. all i did is lock down all the non-private methods with a r/w slim lock. it can barely be called multithreaded coding

                        When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                        1 Reply Last reply
                        0
                        • H honey the codewitch

                          I'm implementing thread safety on a large class after the fact. i hate this. but it has to be done. also Microsoft, what the hell. you didn't put versioning on your dictionary enumerators** ** means when the dictionary is changed the enumerator won't throw like it's supposed to.

                          When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                          Richard DeemingR Offline
                          Richard DeemingR Offline
                          Richard Deeming
                          wrote on last edited by
                          #13

                          honey the codewitch wrote:

                          when the dictionary is changed the enumerator won't throw like it's supposed to

                          Are you sure about that?

                          var d = new Dictionary<int, int>
                          {
                          [1] = 1,
                          [42] = 24,
                          };

                          foreach (var pair in d)
                          {
                          Console.WriteLine($"{pair.Key} = {pair.Value}");
                          d[42] *= 2;
                          }

                          Output:

                          1 = 1
                          InvalidOperationException: Collection was modified; enumeration operation may not execute.

                          Dictionary enumerator versioning | C# Online Compiler | .NET Fiddle[^]


                          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                          H 1 Reply Last reply
                          0
                          • Richard DeemingR Richard Deeming

                            honey the codewitch wrote:

                            when the dictionary is changed the enumerator won't throw like it's supposed to

                            Are you sure about that?

                            var d = new Dictionary<int, int>
                            {
                            [1] = 1,
                            [42] = 24,
                            };

                            foreach (var pair in d)
                            {
                            Console.WriteLine($"{pair.Key} = {pair.Value}");
                            d[42] *= 2;
                            }

                            Output:

                            1 = 1
                            InvalidOperationException: Collection was modified; enumeration operation may not execute.

                            Dictionary enumerator versioning | C# Online Compiler | .NET Fiddle[^]


                            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                            H Offline
                            H Offline
                            honey the codewitch
                            wrote on last edited by
                            #14

                            Yes, I'm sure about that. I'm not talking about the Dictionary class in the BCL I'm talking about the KwData suite they released on codeplex

                            When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups