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. And when you depend on multithreading to be unpredictable, it isn't!

And when you depend on multithreading to be unpredictable, it isn't!

Scheduled Pinned Locked Moved The Lounge
asp-nethelptutorial
48 Posts 15 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

    It's bad enough that multithreaded code is nondeterministic. I propose that it is also meta-nondeterministic: You can not even count on it to be non-deterministic :-\ When you need it to be unpredictable, the scheduler will inexplicably run your timeslices the exact same way, even when threads are executing on different cores, and even reboot to reboot. I'm stuck on creating an *example* simply because I cannot create a situation wherein two secondary threads appear to be in competition (with the third thread being the main application thread) on a dual core ESP32 running FreeRTOS. I can do it where one thread is in competition with the primary thread, but it's as if the scheduler is just a dog when it comes to scheduling between two threads on the same core or something. Grrr. It's bizarre.

    Real programmers use butterflies

    C Offline
    C Offline
    CARNESECCHILuc
    wrote on last edited by
    #22

    How could instructions be non-deterministic when they share the same clock (even on different cores) ? Even random numbers generators are determinitic. I think that the only way to introduce some "chance" in a piece of code is to get information from "outside" : wait for something from a mechanical disk, a keyboard, an other computer...

    H 1 Reply Last reply
    0
    • C CARNESECCHILuc

      How could instructions be non-deterministic when they share the same clock (even on different cores) ? Even random numbers generators are determinitic. I think that the only way to introduce some "chance" in a piece of code is to get information from "outside" : wait for something from a mechanical disk, a keyboard, an other computer...

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

      I'm writing to an external serial port, and it waits for the writes to complete. That should give it some amount of non-determinism.

      Real programmers use butterflies

      1 Reply Last reply
      0
      • H honey the codewitch

        It's bad enough that multithreaded code is nondeterministic. I propose that it is also meta-nondeterministic: You can not even count on it to be non-deterministic :-\ When you need it to be unpredictable, the scheduler will inexplicably run your timeslices the exact same way, even when threads are executing on different cores, and even reboot to reboot. I'm stuck on creating an *example* simply because I cannot create a situation wherein two secondary threads appear to be in competition (with the third thread being the main application thread) on a dual core ESP32 running FreeRTOS. I can do it where one thread is in competition with the primary thread, but it's as if the scheduler is just a dog when it comes to scheduling between two threads on the same core or something. Grrr. It's bizarre.

        Real programmers use butterflies

        O Offline
        O Offline
        obermd
        wrote on last edited by
        #24

        Just remember the following and you'll do fine with multi-threading: Variables and constants aren't.

        1 Reply Last reply
        0
        • H honey the codewitch

          It's bad enough that multithreaded code is nondeterministic. I propose that it is also meta-nondeterministic: You can not even count on it to be non-deterministic :-\ When you need it to be unpredictable, the scheduler will inexplicably run your timeslices the exact same way, even when threads are executing on different cores, and even reboot to reboot. I'm stuck on creating an *example* simply because I cannot create a situation wherein two secondary threads appear to be in competition (with the third thread being the main application thread) on a dual core ESP32 running FreeRTOS. I can do it where one thread is in competition with the primary thread, but it's as if the scheduler is just a dog when it comes to scheduling between two threads on the same core or something. Grrr. It's bizarre.

          Real programmers use butterflies

          M Offline
          M Offline
          milo xml
          wrote on last edited by
          #25

          I'm an admittedly rookie programmer who hasn't done much with multithreading. But wouldn't a Real Time Operating system always do things in the same order? Much like a processor on a PLC? I'm here to learn, so if you have the time to answer that would be great. :)

          H 1 Reply Last reply
          0
          • M milo xml

            I'm an admittedly rookie programmer who hasn't done much with multithreading. But wouldn't a Real Time Operating system always do things in the same order? Much like a processor on a PLC? I'm here to learn, so if you have the time to answer that would be great. :)

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

            Not if there's I/O or something involved, but otherwise, yes, it "probably" will. The reason I say probably is because when you're dealing with multiple cores, they don't run in lockstep with one another. There's a small amount of non-determinism just in the fact that the cores keep their own schedulers and may not have started at precisely the same moment nor even work together*** *** they might synchronize with each other - it's a FreeRTOS-ESP32variant implementation detail I haven't looked into. But that aside, there's also the issue of I/O, which when dealing with an external device, can introduce non-determinism. In my code, I'm outputting to a serial UART, that's connected through an FTDI built bus/USB-bridge controller to a windows PC. Any latency introduced by the PC will ripple back to the thread that's running waiting on I/O.

            Real programmers use butterflies

            M 1 Reply Last reply
            0
            • H honey the codewitch

              You're not wrong at least in the general case, however: 1. This isn't about adding a separate thread in my case. I'm writing a library to allow you to use threads more easily than FreeRTOS otherwise lets you 2. This isn't true if you're writing a library that includes a threadpooler on a system with a primitive scheduler that's prone to starvation. 3. Threads don't care. Hell, my code doesn't care. But it's sure hard to demonstrate out of order execution and resyncing execution order for a *demo* when I can't get the execution order to scramble in the first place 4. Yeah, but this isn't windows, see also, craptastic scheduler 5. If you're doing that to force a context switch I'm not sure what's wrong with you. =) 6. Absolutely true. To that end my library provides you access to *none* of those. :laugh: Seriously though, it offers you a message passing system in the alternative 7. See also, craptastic scheduler

              Real programmers use butterflies

              U Offline
              U Offline
              User 13269747
              wrote on last edited by
              #27

              Quote:

              Absolutely true. To that end my library provides you access to *none* of those. Laugh | :laugh: Seriously though, it offers you a message passing system in the alternative

              Message passing is probably the only way to rein in the complexity of threads. Message-queues is the easiest message-passing interface you will find. I recently did a simple message queueing library (based on pthreads) for a personal project and still managed to get the system to deadlock eventually (only happened on Windows due to different scheduling algorithm[1]). After fixing it I realised that there was no value in a linked-list queue. I implemented my message-queue library as a double-linked list, so that any thread taking a message off of the queue does not block any thread trying to put a message onto the queue. My intention was that threads removing messages from the queue would never hold a lock that threads posting messages to the queue would need (and vice versa). Unfortunately all threads still have to lock the entire queue just to check if (head==tail) in case there is only one item in the queue (then that item is both the head and the tail). This is the stupid way of doing this. Don't do what I did. Instead, do one of the following: 1. Use a fixed-length message queue (either fixed at runtime or fixed at compile-time). This removes quite a lot of the unnecessary complexity; you're going to lock the entire queue for any posting or removal, but you're going to do that anyway with linked-lists too, so no big deal. 2. Address the fixed-length queue using modulus of the length (with appropriate locks); this gives you a circular buffer with no if statements.

              message_t messages[BUFLEN];
              ...
              messages[index % BUFLEN] = new_message; // Posting a message
              ...
              message_t mymessage = messages[index % BUFLEN]; // taking a message off the queue

              The problem with doing this is that it would automatically drop old messages (which, strategically, may be something you want, actually). Also, if you're not using C++ (no smart pointers) that's going to be a memory leak. 3. If your target platform and implementation allows (which it will), use #defines to define a CMPXCHG macro that expands to the assembly of the cmpxchg opcode. You can then use that for a superfast single lock with a sleep in nanoseconds or milliseconds that gradually decrements by a fixe

              H 1 Reply Last reply
              0
              • U User 13269747

                Quote:

                Absolutely true. To that end my library provides you access to *none* of those. Laugh | :laugh: Seriously though, it offers you a message passing system in the alternative

                Message passing is probably the only way to rein in the complexity of threads. Message-queues is the easiest message-passing interface you will find. I recently did a simple message queueing library (based on pthreads) for a personal project and still managed to get the system to deadlock eventually (only happened on Windows due to different scheduling algorithm[1]). After fixing it I realised that there was no value in a linked-list queue. I implemented my message-queue library as a double-linked list, so that any thread taking a message off of the queue does not block any thread trying to put a message onto the queue. My intention was that threads removing messages from the queue would never hold a lock that threads posting messages to the queue would need (and vice versa). Unfortunately all threads still have to lock the entire queue just to check if (head==tail) in case there is only one item in the queue (then that item is both the head and the tail). This is the stupid way of doing this. Don't do what I did. Instead, do one of the following: 1. Use a fixed-length message queue (either fixed at runtime or fixed at compile-time). This removes quite a lot of the unnecessary complexity; you're going to lock the entire queue for any posting or removal, but you're going to do that anyway with linked-lists too, so no big deal. 2. Address the fixed-length queue using modulus of the length (with appropriate locks); this gives you a circular buffer with no if statements.

                message_t messages[BUFLEN];
                ...
                messages[index % BUFLEN] = new_message; // Posting a message
                ...
                message_t mymessage = messages[index % BUFLEN]; // taking a message off the queue

                The problem with doing this is that it would automatically drop old messages (which, strategically, may be something you want, actually). Also, if you're not using C++ (no smart pointers) that's going to be a memory leak. 3. If your target platform and implementation allows (which it will), use #defines to define a CMPXCHG macro that expands to the assembly of the cmpxchg opcode. You can then use that for a superfast single lock with a sleep in nanoseconds or milliseconds that gradually decrements by a fixe

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

                1. I don't write my own concurrency safe queues because FreeRTOS has one and so does .NET so I've not had the need. 2. Yeah, when I wrote a ring buffer in C# I did that 3. I don't know a good reason to use that over say, std::atomic. In my experience, anything that won't support std::atomic won't support atomic CMPXCHG operations at the CPU level anyway, at least not that way. With the atMega2560 for example, IIRC it doesn't have one, forcing you to disable interrupts and then reenable them after the operation is complete. Don't quote me on the mega's capabilities, I'm not an AVR expert. It might be a bad example. Particularly, #3 is curious to me. Why wouldn't you use for example, std::atomic_int? Is it because it's a C++ thing? I use C++ even on 8-bit machines with 4kb of RAM. I just severely limit my use of things like The STL to the bare minimum. std::atomic is one area I use. std::chrono is another. Why? Because writing cross platform CMPXCHNG and timer code is error prone and i don't have access to all that hardware.

                Real programmers use butterflies

                U 1 Reply Last reply
                0
                • H honey the codewitch

                  1. I don't write my own concurrency safe queues because FreeRTOS has one and so does .NET so I've not had the need. 2. Yeah, when I wrote a ring buffer in C# I did that 3. I don't know a good reason to use that over say, std::atomic. In my experience, anything that won't support std::atomic won't support atomic CMPXCHG operations at the CPU level anyway, at least not that way. With the atMega2560 for example, IIRC it doesn't have one, forcing you to disable interrupts and then reenable them after the operation is complete. Don't quote me on the mega's capabilities, I'm not an AVR expert. It might be a bad example. Particularly, #3 is curious to me. Why wouldn't you use for example, std::atomic_int? Is it because it's a C++ thing? I use C++ even on 8-bit machines with 4kb of RAM. I just severely limit my use of things like The STL to the bare minimum. std::atomic is one area I use. std::chrono is another. Why? Because writing cross platform CMPXCHNG and timer code is error prone and i don't have access to all that hardware.

                  Real programmers use butterflies

                  U Offline
                  U Offline
                  User 13269747
                  wrote on last edited by
                  #29

                  Yes, it's because it's a C++ thing, and my queueing library is a C thing (My mention of pthreads should have given it away :-))

                  H 1 Reply Last reply
                  0
                  • U User 13269747

                    Yes, it's because it's a C++ thing, and my queueing library is a C thing (My mention of pthreads should have given it away :-))

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

                    I've used pthreads from C++, so it didn't give it away for me. I was about to write a top level post pondering the overall utility of writing *new* code in C. I love C, but I just can't think of any hardware I've coded for (and i code for little devices) that can't at least host a binary compiled with a C++ compiler. Given that I don't use *most* of C++ (like the STL) when I'm targeting an 8 bit monster, but classes and RAII still help with code management, for example.

                    Real programmers use butterflies

                    U 1 Reply Last reply
                    0
                    • H honey the codewitch

                      Not if there's I/O or something involved, but otherwise, yes, it "probably" will. The reason I say probably is because when you're dealing with multiple cores, they don't run in lockstep with one another. There's a small amount of non-determinism just in the fact that the cores keep their own schedulers and may not have started at precisely the same moment nor even work together*** *** they might synchronize with each other - it's a FreeRTOS-ESP32variant implementation detail I haven't looked into. But that aside, there's also the issue of I/O, which when dealing with an external device, can introduce non-determinism. In my code, I'm outputting to a serial UART, that's connected through an FTDI built bus/USB-bridge controller to a windows PC. Any latency introduced by the PC will ripple back to the thread that's running waiting on I/O.

                      Real programmers use butterflies

                      M Offline
                      M Offline
                      milo xml
                      wrote on last edited by
                      #31

                      Thank you!

                      1 Reply Last reply
                      0
                      • H honey the codewitch

                        I've used pthreads from C++, so it didn't give it away for me. I was about to write a top level post pondering the overall utility of writing *new* code in C. I love C, but I just can't think of any hardware I've coded for (and i code for little devices) that can't at least host a binary compiled with a C++ compiler. Given that I don't use *most* of C++ (like the STL) when I'm targeting an 8 bit monster, but classes and RAII still help with code management, for example.

                        Real programmers use butterflies

                        U Offline
                        U Offline
                        User 13269747
                        wrote on last edited by
                        #32

                        Quote:

                        I was about to write a top level post pondering the overall utility of writing *new* code in C.

                        The overall utility is in the reuse. Writing a library in C means that it can be reused from Python, C++, Java, Perl, Rust, C#, Php, Go, Tcl, Delphi/Lazarus, Pascal, etc. Libraries in C++ can be reused by making C-compatible wrappers around functions, not exposing classes, suppressing exceptions, typedefing structs and prefixing all functions with 'extern "C"'. But then you lose a lot of the value of C++. Lets say you come up with something new and truly useful: a new uber-compression alorithm, or a quantum-computer-proof elliptic curve cryptography. You go ahead and write it in Haskell, or Clojure, or Scala, etc. It definitelywon't take off until someone clones it into a reusable library. Right now we are in a period of computing where it is fashionable to rewrite everything (and also fashionable to pretend that C is the great evil). As far as I can tell, though, the new systems languages are taking a bite out of the C++ mindshare, not out of the C mindshare. C will die the usual way, simply due to attrition as those that know it die off :-)

                        H 1 Reply Last reply
                        0
                        • U User 13269747

                          Quote:

                          I was about to write a top level post pondering the overall utility of writing *new* code in C.

                          The overall utility is in the reuse. Writing a library in C means that it can be reused from Python, C++, Java, Perl, Rust, C#, Php, Go, Tcl, Delphi/Lazarus, Pascal, etc. Libraries in C++ can be reused by making C-compatible wrappers around functions, not exposing classes, suppressing exceptions, typedefing structs and prefixing all functions with 'extern "C"'. But then you lose a lot of the value of C++. Lets say you come up with something new and truly useful: a new uber-compression alorithm, or a quantum-computer-proof elliptic curve cryptography. You go ahead and write it in Haskell, or Clojure, or Scala, etc. It definitelywon't take off until someone clones it into a reusable library. Right now we are in a period of computing where it is fashionable to rewrite everything (and also fashionable to pretend that C is the great evil). As far as I can tell, though, the new systems languages are taking a bite out of the C++ mindshare, not out of the C mindshare. C will die the usual way, simply due to attrition as those that know it die off :-)

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

                          The simplicity of it for expressing algorithms one has developed is certainly a win, but honestly, I'd rather read it in C# than C if I was going to port it. In practice, I've ported C# stuff to C++ on IoT things several times - everything from a thread synchronization library to a streaming JSON parser with a less than 4kB footprint not tied to document size. C# is just easy to read, IMO but that's just one dev's opinion based on dev's experience. Some of that could have easily been made into C. I don't think wrapping things with extern loses you valuable C++, but exporting C also is kind of like writing new code for "C" so it wasn't something that was on my radar when I responded. Importing code that's compiled in C is another matter. I don't think "C" is evil, so maybe I'm just not fashionable. I'm just seeing less of a point for it these days. The beauty of C++ is you *don't* have to rewrite all that C code. You can use it at the source or binary level in your C++ apps.

                          Real programmers use butterflies

                          U 1 Reply Last reply
                          0
                          • H honey the codewitch

                            It's bad enough that multithreaded code is nondeterministic. I propose that it is also meta-nondeterministic: You can not even count on it to be non-deterministic :-\ When you need it to be unpredictable, the scheduler will inexplicably run your timeslices the exact same way, even when threads are executing on different cores, and even reboot to reboot. I'm stuck on creating an *example* simply because I cannot create a situation wherein two secondary threads appear to be in competition (with the third thread being the main application thread) on a dual core ESP32 running FreeRTOS. I can do it where one thread is in competition with the primary thread, but it's as if the scheduler is just a dog when it comes to scheduling between two threads on the same core or something. Grrr. It's bizarre.

                            Real programmers use butterflies

                            S Offline
                            S Offline
                            Stuart Dootson
                            wrote on last edited by
                            #34

                            What scheduling algorithm is being used? IIRC, FreeRTOS has multiple scheduling algorithms you can choose between, which might affect the amount of non-determinism?

                            Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                            H 1 Reply Last reply
                            0
                            • S Stuart Dootson

                              What scheduling algorithm is being used? IIRC, FreeRTOS has multiple scheduling algorithms you can choose between, which might affect the amount of non-determinism?

                              Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

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

                              Hmm. The one I'm using is a variant ported to the ESP32 to use the ESP-IDF, by Espressif. Their forums, and the FreeRTOS documentation I've encountered online both suggest that round robin is used for any thread created on the same priority level on the same scheduler (core) This leads to starvation. The forums warn of it particularly, but so does setting different priorities, just for slightly different reasons. There's no "salting" done in their scheduler according to any of the documentation I've encountered.

                              Real programmers use butterflies

                              S 1 Reply Last reply
                              0
                              • H honey the codewitch

                                Hmm. The one I'm using is a variant ported to the ESP32 to use the ESP-IDF, by Espressif. Their forums, and the FreeRTOS documentation I've encountered online both suggest that round robin is used for any thread created on the same priority level on the same scheduler (core) This leads to starvation. The forums warn of it particularly, but so does setting different priorities, just for slightly different reasons. There's no "salting" done in their scheduler according to any of the documentation I've encountered.

                                Real programmers use butterflies

                                S Offline
                                S Offline
                                Stuart Dootson
                                wrote on last edited by
                                #36

                                I was under the impression that round robin scheduling would guarantee equal time for pre-emptive tasks with the same priority (presuming no higher priority task preempts *them*), which should mean no starvation. Guess I was under the wrong impression.

                                Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                                H 1 Reply Last reply
                                0
                                • S Stuart Dootson

                                  I was under the impression that round robin scheduling would guarantee equal time for pre-emptive tasks with the same priority (presuming no higher priority task preempts *them*), which should mean no starvation. Guess I was under the wrong impression.

                                  Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

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

                                  In the case where thread A and thread B operate at the same priority, everything works until we start looking at who to unblock. It will always unblock the next thread in the round robin list. if thread A is coded where it sleeps twice for every time thread B sleeps once, I think it will lead to one of them being starved. I'm not entirely confident in that without testing it, but it's easy for me to starve a thread in the wild on this OS. If it were me i would have stored the machine tick based timestamp on the last time the thread was unsuspended. all priorities considered equal, i would use that to determine which to wake up next, and then if further disambiguation was necessary (doubtful) it could round robin, but i don't think that's even necessary.

                                  Real programmers use butterflies

                                  1 Reply Last reply
                                  0
                                  • H honey the codewitch

                                    The simplicity of it for expressing algorithms one has developed is certainly a win, but honestly, I'd rather read it in C# than C if I was going to port it. In practice, I've ported C# stuff to C++ on IoT things several times - everything from a thread synchronization library to a streaming JSON parser with a less than 4kB footprint not tied to document size. C# is just easy to read, IMO but that's just one dev's opinion based on dev's experience. Some of that could have easily been made into C. I don't think wrapping things with extern loses you valuable C++, but exporting C also is kind of like writing new code for "C" so it wasn't something that was on my radar when I responded. Importing code that's compiled in C is another matter. I don't think "C" is evil, so maybe I'm just not fashionable. I'm just seeing less of a point for it these days. The beauty of C++ is you *don't* have to rewrite all that C code. You can use it at the source or binary level in your C++ apps.

                                    Real programmers use butterflies

                                    U Offline
                                    U Offline
                                    User 13269747
                                    wrote on last edited by
                                    #38

                                    Quote:

                                    The beauty of C++ is you *don't* have to rewrite all that C code. You can use it at the source or binary level in your C++ apps.

                                    But that was my point, sort of... anything I write that I want to reuse has to be written in C (or, lately, Rust). If I write it in C I can use it from anywhere and any language. If I write in in C++ I can't. If I write in C# I have even fewer opportunities to reuse.

                                    H 1 Reply Last reply
                                    0
                                    • U User 13269747

                                      Quote:

                                      The beauty of C++ is you *don't* have to rewrite all that C code. You can use it at the source or binary level in your C++ apps.

                                      But that was my point, sort of... anything I write that I want to reuse has to be written in C (or, lately, Rust). If I write it in C I can use it from anywhere and any language. If I write in in C++ I can't. If I write in C# I have even fewer opportunities to reuse.

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

                                      I think we're talking about two different things because time after time I have a much easier go of porting C# to C than the other way around.

                                      Real programmers use butterflies

                                      U 1 Reply Last reply
                                      0
                                      • H honey the codewitch

                                        I think we're talking about two different things because time after time I have a much easier go of porting C# to C than the other way around.

                                        Real programmers use butterflies

                                        U Offline
                                        U Offline
                                        User 13269747
                                        wrote on last edited by
                                        #40

                                        Quote:

                                        I think we're talking about two different things because time after time I have a much easier go of porting C# to C than the other way around.

                                        You're correct, I am not talking about porting, I am talking about using. Anything you write in C# can only be used inside the .net runtime. If you want to use it elsewhere yo have to port it. With C, and some care, anything written can be used by any other language without porting ... like libpng (usable by all languages without porting, or libzip, or almost anything else in my system (yours too, probably). A good example is SQLite (the most-used and most deployed library in the world according to the statistics from MS): if it were written in C#, or in C++, or in anything else other than C, it would not be as useful as it is because it would not be usable from all languages.

                                        H 1 Reply Last reply
                                        0
                                        • U User 13269747

                                          Quote:

                                          I think we're talking about two different things because time after time I have a much easier go of porting C# to C than the other way around.

                                          You're correct, I am not talking about porting, I am talking about using. Anything you write in C# can only be used inside the .net runtime. If you want to use it elsewhere yo have to port it. With C, and some care, anything written can be used by any other language without porting ... like libpng (usable by all languages without porting, or libzip, or almost anything else in my system (yours too, probably). A good example is SQLite (the most-used and most deployed library in the world according to the statistics from MS): if it were written in C#, or in C++, or in anything else other than C, it would not be as useful as it is because it would not be usable from all languages.

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

                                          That's weird because my JSON parser was ported from C# and it doesn't require the .NET runtimes. Same with my threading and synchronization library (also originally written in C#) And the only place you can run C without porting is C++, and even that is not always true. Furthermore, as soon you declare int* foo; Or any "array" of indeterminate size in C you've pretty much nixed any dream of making it work on anything without pointers- "without porting" sorry, but what are you even talking about?

                                          Real programmers use butterflies

                                          U 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