Okay so here's my idea for threading in BlitzMax. Mark, please take a look and see what you think. You said in a previous thread that you wanted an elegant solution that was something non-standard. I think I've got something that fits that bill here.
The idea is that once a thread is kicked off, the only way to communicate with it is through events and an event loops.
So in order to control threads we define these new commands:
A thread object is descendant from TThread and provides a Run method that is called by StartThread. Each thread is given it's own copy of the Garbage Collector.
When ThreadEmitEvent is called, a copy of the Event object is created by the Garbage Collector for the thread ID provided, then placed on that thread's event queue. This thread can then pick up the event object at it's convenience: this assumes that a thread that expects to receive events will be running an event loop.
To solve the object copying problem, we define a "thread safe" event object which can easily be copied using a small algorithm (validating this and doing the copying would be supported by introspection or at a lower level in the C code more likely).
TThreadEvent
- All fields must be of one of these types:
- A simple number
- String object
- Another TThreadEvent descendant
This gives a well defined format that we can easily copy.
I don't know what the Garbage Collector looks like internally, but I assume that this could work. Basically, threads can be looked at from the perspective of the GC as an external hardware resource: they simply generate events that can be read by other threads. In principal this should require no significant changes to the GC because it only manages the objects it allocates memory for: a thread cannot directly pass an object to any other thread, or make calls to functions in other threads so multiple GCs cannot step on each other's toes.
Edit: fixed some mistakes
The idea is that once a thread is kicked off, the only way to communicate with it is through events and an event loops.
So in order to control threads we define these new commands:
ThreadStart:Int(ThreadObject) ' Returns an integer ID for the thread ThreadStop ID:Int ' Stop the thread ID given ThreadEmitEvent ID:Int, Event:TThreadEvent ' Send an event to a thread. The only way for threads to communicate.
A thread object is descendant from TThread and provides a Run method that is called by StartThread. Each thread is given it's own copy of the Garbage Collector.
When ThreadEmitEvent is called, a copy of the Event object is created by the Garbage Collector for the thread ID provided, then placed on that thread's event queue. This thread can then pick up the event object at it's convenience: this assumes that a thread that expects to receive events will be running an event loop.
To solve the object copying problem, we define a "thread safe" event object which can easily be copied using a small algorithm (validating this and doing the copying would be supported by introspection or at a lower level in the C code more likely).
TThreadEvent
- All fields must be of one of these types:
- A simple number
- String object
- Another TThreadEvent descendant
This gives a well defined format that we can easily copy.
I don't know what the Garbage Collector looks like internally, but I assume that this could work. Basically, threads can be looked at from the perspective of the GC as an external hardware resource: they simply generate events that can be read by other threads. In principal this should require no significant changes to the GC because it only manages the objects it allocates memory for: a thread cannot directly pass an object to any other thread, or make calls to functions in other threads so multiple GCs cannot step on each other's toes.
Edit: fixed some mistakes