Saturday 13 July 2019

Threads Mashup

After writing this post I was thinking a bit about how we could do to cancel a chain of async-await calls in JavaScript. Standard promises are not cancellable (unless that you implement your own mechanism, as they do in Bluebird), but I'm thinking more about at least skipping the ensuing await calls. This post gives some good hints on how to proceed. This usage of a Cancellation Token sent me back to the C#-Tasks world, where Cancellation Tokens are the mechanism used for cancelling tasks. Tasks in .Net are used for 2 different things, IO async operations (where the Task does not involve a new Thread, same as Promises in JavaScript), and CPU intensive operations where you do a Task.Run to run the code in a separate thread and leverage your CPU cores. The rest of this article deals with the Threading and Tasks involving threads" world, not with the IO async operations represented with Promises/Tasks universe.

Cancellation Tokens are a collaborative mechanism. Someone tells the code running in a Thread created via Task.Run or Task.Factory.Start "please stop" and that code is occasionally checking for that kind of requests (through the Cancellation Token) and stops itself. You could use something similar for Threads started via the old Thread.Start mechanism. Use some property, closure variable, whatever shared between the caller and the callee, and have the callee checking for it and quitting if requested.

Threads started with Thread.Start provide you with a more radical cancellation mechanism, Thread.Abort. There's no collaboration here, someone tells the Runtime to stop the thread, and the runtime will do so if certain circumstances are met. Canceling a Thread without its permission can be risky, it can let the system in an unstable state, so some restrictions apply:

  • Thread.Abort will not try to cancel a thread that is running native code. It makes sense, but causes some absurd situation. A thread stopped in a Console.ReadLine() is deep into native code, so it can not be aborted, but this is a pretty harmless operation.
  • The thread is given the chance to manage these abortions. A ThreadAbortException is thrown inside the thread, that can catch it and do some clean up. ThreadAbortExcpetion is a very special exception, even if you catch it, it gets re-thrown, so it will ultimately kill the thread. In order to avoid that, the thread has to call Thread.ResetAbort() inside the catch block.

Related to this, I was revisiting how unhandled exceptions in one thread affect the whole process. An unhandled exception will not just kill the involved thread, but the whole process. This is the same regardless of whether the Thread is foreground or background (background threads are those that will not keep a process running if all the foreground ones are finished). This is not affected either by whether the Thread is a normal thread or a .Net ThreadPool one.

ThreadAbortExceptions are also particular in this sense. As I've said, if we don't call ResetAbort the exception will get to the top of the thread and finish it, but it won't crash the process.

Finally, I've learnt that since .Net 4.5 unhandled exceptions in a Thread started with Task.Run (or Task.Factory.Start) will not tear down the process. I guess Task.Run wraps the call to the provided delegate in a try-catch block.

An additional note, Thread.Abort is not available in .Net Core

Basic REST stuff

I have a very limited knowledge (being optimistic) about REST API's (I mean, using the right url's, the HATEOAS thing...) and the other day I came across a couple of points that I'll share.

I was doing a GET request and the last parameter was a decimal value, something like this:

http://myserver.org/documents/docId/version

http://myserver.org/documents/a123bb/1.1

The above would give a server error (thrown by the http server itself, not by the ASP.NET Web API controller). The problem is because finishing the url with a ".1" the http server was interpreting that I was requesting a file. You can easily fix this by adding a "/" at the end, I mean:

http://myserver.org/documents/a123bb/1.1/

The next issue I came across was with an optional parameter not placed at the end of the url. I want the children of a document for a given version, but the version parameter is optional, as if missing we'll use the last available document. I wanted to use something like this:

http://myserver.org/documents/a123bb/1.1/children

http://myserver.org/documents/a123bb/children

[HttpGet]
[Route("{docId}/{version}/children")]
public HttpResponseMessage GetDocumentChildren(string docId, string version = null){}

The above would not work for the second url. The controller would not understand that version was missing there. In the end I had to add a second route to the controller, so I ended up with this:

[HttpGet]
[Route("{docId}/{version}/children")]		
[Route("{docId}/children")]
public HttpResponseMessage GetDocumentChildren(string docId, string version = null){}	

Arrow Functions and binding

When doing some tests with Jasmine I wanted to spy on one method invoked from the constructor (I mean method and constructor of the same class). As you need to set the spy before having the instance created, you'll have to spy on the class method (so you'll end up spying on each instance of the class, not just a particular one), not on the instance method. As you know, JavaScript classes are syntax sugar on top of the prototypes mechanism. Apart from "recording" the call, I did not want to invoke the original method, but a function assigning some mock data to one property of the object. So I was setting my spy like this

spyOn(MyClass.prototype, "myMethod").and.callFake(() => this.items = mockData.items);

let myInstance = new MyClass();
console.log(myInstance.items); //undefined!

I had read that the function provided to callFake would receive as this the object on which we are spying, but the above code was not setting the property. Can you spot the problem? Well, it's simple, we should use a function expression rather than an arrow function:

spyOn(MyClass.prototype, "myMethod").and.fake(function(){
 this.items = mockData.items;
});

Other than its cool syntax Arrow functions trap the lexical this rather than using a dynamic this. This is very useful for event handlers, callbacks... and has made the typical "self-closure" pattern disappear, I mean:

self = this;
myButton.addEventListener("click", function(){
 self.myMethod();
});

//has given place to:
myButton.addEventListener("click", () => this.myMethod());

An arrow function binds to the function the this that exists at the moment of creating the function. The arrow function gets bound to that this similar to when you call function.prototype.bind. Once you have a bound function, calling bind on it again will not have a real effect. You get a new function wrapping the bound one, but the invokation will call the internal function with the first bound this. I guess function.prototype.bind creates a wrapper that uses function.prototype.call, and function.prototype.call is useless with bound functions:


class Person{
 constructor(name){
  this.name = name;
 }
 
 sayHi(){
  return "Hi, I'm " + this.name;
 }
}

let f1 = Person.prototype.sayHi.bind({name: "Francois"});
console.log(f1());

console.log(f1.call({name: "Chloe"}));

let f2 = f1.bind({name: "Chloe"});
console.log(f2());

//Hi, I'm Francois
//Hi, I'm Francois
//Hi, I'm Francois

I assume Jasmine is using using Function.prototype.bind to provide the this to the function invoked from callFake, so an arrow won't make it.

Notice that both functions created with Function.prototype.bind and arrow functions do not have a .prototype property (obviously they still have a [[Prototype]] property as every JavaScript object) and can not be used as a constructor with new (you'll get an "is not a constructor" error)