I'm trying to implement OpenComputers support for a mod I'm making. The mod in question already supports ComputerCraft. I've managed to add OC support for everything else save for a radio transmitter block.
The block / tile entity in question is designed to allow sending data over a channel, but is restricted to sending a certain amount of data within a timeframe. To be exact, you can send 2205 bytes over a channel 5 times a second (0.2 seconds per packet).
To this end, the transmission method for ComputerCraft waits a certain amount of time if data has already been sent:
sendCache is whether data has already been sent to a certain channel, and sendEventWhenSend adds the computer into a queue, after which the thread responsible for running the radio (as well as sending packets to players; there's a pocket radio item to play the radio data as audio). The queue is cleared on every send by sending an event to all of the computers in the queue, and the pullEvent function will block until this event is sent - which makes the computer idle and wait until the packet currently in the queue is sent.
For OpenComputers, I've failed to find such an alternative. I'm aware of Context#pause, but it requires a specific determined amount of time to pause for - and while the radio thread is supposed to be run every 200 ms as timed by the server scheduler, I cannot be certain that estimating the time would be correct - if it's too early, the whole thing may break apart, while if it's too late, it wastes processing time on the computer.
I was thinking of using direct = true and simply using semaphores - adding the semaphore into the same radio queue, waiting it (acquire) and then signaling it (release) in the radio thread, but this actually causes the entire server to lag - if I add a print statement into the callback, 9 out of 10 calls still come directly from the server thread, so forcing it to sleep causes everything else to stop as well.
I have noticed Machine#popSignal, but I'm not certain how to retrieve a Machine instance from a ManagedEnvironment, and it doesn't seem popSignal is blocking anyway ("return a signal or null if the queue was empty").
Is there any better way to achieve what I'm trying to do other than spinning (check if we've sent a packet, if not, Context#pause and check again), which feels wasteful?
edit: It seems that using Context.pause and spinning causes all other computers to slow down (even if I try to predict the time beforehand and spin afterwards if it isn't sufficient), which makes a better solution (that could yield) even more urgent.
You can post now and register later.
If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.
I'm trying to implement OpenComputers support for a mod I'm making. The mod in question already supports ComputerCraft. I've managed to add OC support for everything else save for a radio transmitter block.
The block / tile entity in question is designed to allow sending data over a channel, but is restricted to sending a certain amount of data within a timeframe. To be exact, you can send 2205 bytes over a channel 5 times a second (0.2 seconds per packet).
To this end, the transmission method for ComputerCraft waits a certain amount of time if data has already been sent:
sendCache is whether data has already been sent to a certain channel, and sendEventWhenSend adds the computer into a queue, after which the thread responsible for running the radio (as well as sending packets to players; there's a pocket radio item to play the radio data as audio). The queue is cleared on every send by sending an event to all of the computers in the queue, and the pullEvent function will block until this event is sent - which makes the computer idle and wait until the packet currently in the queue is sent.
For OpenComputers, I've failed to find such an alternative. I'm aware of Context#pause, but it requires a specific determined amount of time to pause for - and while the radio thread is supposed to be run every 200 ms as timed by the server scheduler, I cannot be certain that estimating the time would be correct - if it's too early, the whole thing may break apart, while if it's too late, it wastes processing time on the computer.
I was thinking of using direct = true and simply using semaphores - adding the semaphore into the same radio queue, waiting it (acquire) and then signaling it (release) in the radio thread, but this actually causes the entire server to lag - if I add a print statement into the callback, 9 out of 10 calls still come directly from the server thread, so forcing it to sleep causes everything else to stop as well.
I have noticed Machine#popSignal, but I'm not certain how to retrieve a Machine instance from a ManagedEnvironment, and it doesn't seem popSignal is blocking anyway ("return a signal or null if the queue was empty").
Is there any better way to achieve what I'm trying to do other than spinning (check if we've sent a packet, if not, Context#pause and check again), which feels wasteful?
edit: It seems that using Context.pause and spinning causes all other computers to slow down (even if I try to predict the time beforehand and spin afterwards if it isn't sufficient), which makes a better solution (that could yield) even more urgent.
Edited by CosmoConsoleupdated
Link to post
Share on other sites