How to safely select across channels where some may get concurrently closed? - multithreading

While answering a question I attempted to implement a setup where the main thread joins the efforts of the CommonPool to execute a number of independent tasks in parallel (this is how java.util.streams operates).
I create as many actors as there are CommonPool threads, plus a channel for the main thread. The actors use rendezvous channels:
val resultChannel = Channel<Double>(UNLIMITED)
val poolComputeChannels = (1..commonPool().parallelism).map {
actor<Task>(CommonPool) {
for (task in channel) {
task.execute().also { resultChannel.send(it) }
}
}
}
val mainComputeChannel = Channel<Task>()
val allComputeChannels = poolComputeChannels + mainComputeChannel
This allows me to distribute the load by using a select expression to find an idle actor for each task:
select {
allComputeChannels.forEach { chan ->
chan.onSend(task) {}
}
}
So I send all the tasks and close the channels:
launch(CommonPool) {
jobs.forEach { task ->
select {
allComputeChannels.forEach { chan ->
chan.onSend(task) {}
}
}
}
allComputeChannels.forEach { it.close() }
}
Now I have to write the code for the main thread. Here I decided to serve both the mainComputeChannel, executing the tasks submitted to the main thread, and the resultChannel, accumulating the individual results into the final sum:
return runBlocking {
var completedCount = 0
var sum = 0.0
while (completedCount < NUM_TASKS) {
select<Unit> {
mainComputeChannel.onReceive { task ->
task.execute().also { resultChannel.send(it) }
}
resultChannel.onReceive { result ->
sum += result
completedCount++
}
}
}
resultChannel.close()
sum
}
This gives rise to the situation where mainComputeChannel may be closed from a CommonPool thread, but the resultChannel still needs serving. If the channel is closed, onReceive will throw an exception and onReceiveOrNull will immediately select with null. Neither option is acceptable. I didn't find a way to avoid registering the mainComputeChannel if it's closed, either. If I use if (!mainComputeChannel.isClosedForReceive), it will not be atomic with the registration call.
This leads me to my question: what would be a good idiom to select over channels where some may get closed by another thread while others are still live?

The kotlinx.coroutines library is currently missing a primitive to make it convenient. The outstanding proposal is to add receiveOrClose function and onReceiveOrClosed clause for select that would make writing code like this possible.
However, you will still have to manually track the fact that your mainComputeChannel was closed and stop selecting on it when it was. So, using a proposed onReceiveOrClosed clause you'll write something like this:
// outside of loop
var mainComputeChannelClosed = false
// inside loop
select<Unit> {
if (!mainComputeChannelClosed) {
mainComputeChannel.onReceiveOrClosed {
if (it.isClosed) mainComputeChannelClosed = true
else { /* do something with it */ }
}
}
// more clauses
}
See https://github.com/Kotlin/kotlinx.coroutines/issues/330 for details.
There are no proposals on the table to further simplify this kind of pattern.

Related

Is there a function to parse a ThreadId into an i32 or other primitive?

I'm looking for a solution to test which threadid my program is in:
let t1 = thread::spawn(move|| {
if thread::current().id() == 2 {
println!("yes");
}
});
The above fails since it is looking for a ThreadId
I have also tried using
if thread::current().id() == ThreadId(NonZeroU64::new(2).unwrap()) {
//do stuff
}
But since ThreadId is private this does not work
Also there is an issue currently with thread::current().id().as_u64() being unstable.
So I was wondering if there is an easy way to get the number from thread::current().id()?
Its possible to print the thread::current().id() to the console as ThreadId(2) but I'm having trouble trying to compare this to another variable before I join the thread..

How to find first desired result from kotlin coroutines Deferred<> (server)

I’ve built a sharding library and i’m trying to add coroutine functionality to it. In the following snippet it returns the first true result that it finds:
override fun emailExists(email: String): Boolean {
return runBlocking {
shards
.asyncAll { userDao.emailExists(email) }
.map { it.await() }
.firstOrNull { it }
} ?: false
}
the shards.asyncAll method is:
fun <T> async(
shardId: Long,
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T): Deferred<T> {
return scope.async(context, start) {
selectShard(shardId)
block()
}
}
fun <T> asyncAll(
shardIds: Collection<Long> = this.shardIds,
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T): List<Deferred<T>> {
return shardIds.map { async(it, context, start, block) }
}
This works, but it consults the shards in order for their return, meaning if the first shard takes a very long time to return and it doesn't return true but the second shard returns immediately with a value of true we're still waiting as long as the first shard took to return. Is there a better way to wait on values for a collection of Deferred<>'s and process them in the order that they return so that I can exit as early as possible?
Even if you were to get your answer early, runBlocking would still wait for all the coroutines you started to complete before returning.
In order to run the kind of coroutine race you're looking for:
When the first task completes with true, it needs store that result and cancel the parent job of all the other tasks; and
The other tasks should properly abort when cancelled.
Unfortunately, I'm pretty sure Kotlin doesn't include a function that does this, so you have to do it yourself. The easiest way is probably to have each throw an exception that indicates a true result. You can then use awaitAll on the group, catch the exception, and extract the result.

Running self-feeding channels in Perl 6

I would like to set up a number of threads operating concurrently on a channel, and every one of those threads should be also feeding the channel. One of the threads would decide when to stop. However, this is the closest I have come to doing that:
use Algorithm::Evolutionary::Simple;
my $length = 32;
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
my $channel-one = $supply.Channel;
my $pairs-supply = $supply.batch( elems => 2 );
my $channel-two = $pairs-supply.Channel;
my $single = start {
react {
whenever $channel-one -> $item {
say "via Channel 1:", max-ones($item);
}
}
}
my $pairs = start {
react {
whenever $channel-two -> #pair {
my #new-chromosome = crossover( #pair[0], #pair[1] );
say "In Channel 2: ", #new-chromosome;
$supplier.emit( #new-chromosome[0]);
$supplier.emit( #new-chromosome[1]);
}
}
}
await (^10).map: -> $r {
start {
sleep $r/100.0;
$supplier.emit( random-chromosome($length) );
}
}
$supplier.done;
This stops after a number of emissions. And it's probably not running concurrently anyway. I am using channels instead of supplies and taps because these are not run concurrently, but asynchronously. I need supplies because I want to have a seudo-channel that takes the elements in pairs, as it's done above; I haven't seen the way of doing that with pure channels.
There is no difference above if I change the supply's emit to channel's send.
So several questions here
Are these react blocks run in different threads? If not, what would be the way of doing that?
Even if they are not, why does it stop even if $pairs is emitting to the channel all the time?
Could I have "batch" channels created automatically from single-item channels?
Update 1: if I eliminate $supplier.done from the end, it will just block. If I create a promise in whenever, one for each read, it just blocks and does nothing.
The answer is here, stripped down to the minimum necessary
my Channel $c .= new;
my Channel $c2 = $c.Supply.batch( elems => 2).Channel;
my Channel $output .= new;
my $count = 0;
$c.send(1) for ^2;
my $more-work = start react whenever $c2 -> #item {
if ( $count++ < 32 ) {
$c.send( #item[1]);
my $sum = sum #item;
$c.send( $sum );
$output.send( $sum );
} else {
$c.close;
}
}
await $more-work;
loop {
if my $item = $output.poll {
$item.say
} else {
$output.close;
}
if $output.closed { last };
}
A second channel that batches the first channel every two elements is used via the creation of a supply from a channel ($c.Supply), batching that supply in batches of two (batch( elems => 2)) and turning it back into a channel. A third channel is created for output.
In order to not exhaust the supply and hang the channel, every second element that is read from the first (and actually, only) channel is put back there. So the second channel that reads in twos is never hanged or waiting for new elements.
An output channel is created for every new element, and an external counter to finish the operation when it's needed; that output channel is read in a non-blocking way, and closed when there's nothing left to read in the last line.
To answer precisely to my original questions:
Yes, they are, only they are stealing elements from each other.
Because the two threads were reading from the same channel. The first one to stumble into an element, reads it.
Yes, by turning channels into supplies, batching them and turning them back into channels. Only bear in mind that they are not copies, they will be sharing the self same elements.

Initialize a Blockly Mutator within JavaScript

Hi,
as far as I know, custom blocks in Blockly can be defined wether in JSON or in JavaScript, but how can a mutator be initialized in JavaScript?
with JSON:
Blockly.defineBlocksWithJSONArray([
{....
"mutator": "myMutatorName"
});
Then the Mutator_MIXIN must be defined and with Blockly.Extension.registerMutator('myMutatorName', Blockly.myMutator_MIXIN, null, null) the mutator is added to the Block.
with JavaScript:
Blockly.Blocks['blockName'] = {
init: function() = {
....
??? this.setMutator(???)???
};
}
So how can this be done in JavaScript?
Kind regards
a new one
I might be just a little bit late here, but I'll leave the answer anyway for those who need a bit more concrete example.
In JavaScript, you don't actually need to bind a mutator to your block, you just need to define mutationToDom() and domToMutation(xmlElement) functions, like so:
Blockly.Blocks['my_custom_block'] = {
init() {
// Define your basic block stuff here
},
// Mutator functions
mutationToDom() {
let container = document.createElement('mutation');
// Bind some values to container e.g. container.setAttribute('foo', 3.14);
return container;
},
domToMutation(xmlElement) {
// Retrieve all attributes from 'xmlElement' and reshape your block
// e.g. let foo = xmlElement.getAttribute('foo');
// this.reshape(foo);
},
// Aux functions
reshape(param){
// Reshape your block...
}
}
Blockly will automagically take care of the rest and allow you to treat your block as dynamic one.
And if you need to used Mutator Editor UI, you must define decompose(workspace) and compose(containerBlock) functions and call this.setMutator(...) to set which blocks are used in the Mutator Editor UI, like so:
Blockly.Blocks['my_custom_block'] = {
init() {
// Define your basic block stuff here
// Set all block that will be used in Mutator Editor UI, in this
// case only 'my_block_A' and
this.setMutator(new Blockly.Mutator(['my_block_A', 'my_block_B']));
},
// Mutator functions
mutationToDom() {
// Same as previous example
},
domToMutation(xmlElement) {
// Same as previous example
},
decompose(workspace) {
// Decomposeyour block here
},
compose(containerBlock) {
// Compose your block here
},
// Aux functions
reshape(param){
// Same as previous example
}
}
Hope that these short examples help someone :)
You have to declare how the xml is loaded to dom, and how it is saved to xml and redrawn. Also notice how it attaches a mutator to a block element in case that is the only part you need to reference a mutator already present.
init: initFunction (Like you have declared.)
mutationToDom: MutationToDom,
domToMutation: DomToMutation,
updateShape_: UpdateShape`
If all you require is to create a reference to a mutator then what you need is an element of this kind, which we will programatically create in a bit:
<mutation mutator_name="true"></mutation>
The following snippet is an example of the extra functions mutationToDom, DomtoMutation UpdateShape which attaches extra input conditionally. I have a block with a checkbox that when enabled, adds an extra input.
function MutationToDom() {
var container = document.createElement('mutation');
var continueOnError = (this.getFieldValue('HasCONTINUE') == 'TRUE');
container.setAttribute('continueOnError', continueOnError);
return container;
}
function DomToMutation(xmlElement) {
var continueOnError = (xmlElement.getAttribute('continueOnError') == 'true');
this.updateShape_(continueOnError);
}
function UpdateShape(continueOnError) {
// Add or remove a Value Input.
if (continueOnError) {
this.appendValueInput("CONTINUE_ON_ERROR")
.setCheck('CONTINUE_ON_ERROR');
} else {
if (this.childBlocks_.length > 0) {
for (var i = 0; i < this.childBlocks_.length; i++) {
if (this.childBlocks_[i].type == 'continue_on_error') {
this.childBlocks_[i].unplug();
break;
}
}
}
this.removeInput('CONTINUE_ON_ERROR');
}
}

Parameter read when Task runs, not when declared

I'm trying to find out how to do this properly. What's happening is in "Task MyTask = new Task(() => Match.UserObject.InitUser(tmpUserObject));", tmpUserObject is getting evaluated when the task runs and not when it's declared. Since this seems to be a "feature", there must be a proper way to use the value of tmpUserObject at the time the task is declared.
Thanks :-)
Match.UserObject tmpUserObject;
while (myReader.Read())
{
if (tmpDict.TryGetValue(UserID, out tmpUserObject))
{
tmpUserObject.vchSchoolID.Add(myReader.GetString(5));
}
else
{
tmpUserObject = new Match.UserObject();
//Assign some values from reader...
//Do any processing eg. DoubleMetaphone pre-computation...etc...
Task MyTask = new Task(() => Match.UserObject.InitUser(tmpUserObject));
TaskList.Add(MyTask);
}
}
//Block until all the tasks are done
Task[] MyTaskArray = TaskList.ToArray();
Task.WaitAll(MyTaskArray);
From what I can tell of your code, tmpUserObject is a class instance. It is never "evaluated". The lambda that you pass to the task ( () => Match.UserObject.InitUser(tmpUserObject) ) is evaluated when the task is run, which does happen asynchronously. That's the purpose of the Task object.
What do you actually mean when you say "use the value of tmpUserObject"?
EDIT: To capture the value, you need to assign it to a new variable with each iteration. You can do this simply by re-scoping the variable to inside the loop:
while (myReader.Read())
{
// Since we moved this inside the loop, the variable's scope has changed.
Match.UserObject tmpUserObject;
if (tmpDict.TryGetValue(UserID, out tmpUserObject))
{
tmpUserObject.vchSchoolID.Add(myReader.GetString(5));
}
else
{
tmpUserObject = new Match.UserObject();
//Assign some values from reader...
//Do any processing eg. DoubleMetaphone pre-computation...etc...
Task MyTask = new Task(() => Match.UserObject.InitUser(tmpUserObject));
TaskList.Add(MyTask);
}
}
That's called a closure.
It's one of C#'s more powerful features.
If you want to evaluate the expression in advance, you can put it in a separate variable outside the lambda.

Resources