Apex Syntactic Sugar Enabled by Mutexes

In the last post we looked at the possible API for a Mutex object and how that could be used to protect access to a queue/executor model. This required a lot of boilerplate code. What if the language/compiler were enhanced to take advantage of these Mutex objects simplifying developers life.

On Java there is the concept of synchronised methods (and blocks). What might this look like on Apex?  In Java synchronised is a keyword and is used on methods like this

public synchronised void myMethod() {
}

This means that only one thread can be executing this method at a time.  Access to this method is synchronised by a Mutex without any further work by the developer. This is roughly analogous to

public void myMethod() {
 Mutex m = new Mutex(‘myMethod’);
 m.lock();
 …
 m.unlock();
}

It’s easy to imagine the exact same syntax and semantics being ported to Apex. However lessons from the Java world should inform any Apex implementation.  Many times in Java this is too inflexible. A couple of improvements we might want:

  • Ability to synchronise across multiple methods (to share the same mutex across multiple methods)

  • Some flexibility in the mutex to still control parallelism but allow multiple unrelated executions to run

The use case for the first is pretty clear. We might have multiple methods that all access the same protected resource. Access to any of these methods needs to be synchronised behind the same Mutex

If we change the synchronised directive from a modifier to an annotation we could allow for this. And better maintain “normal” Apex code compatibility.

@synchronised(name=“queue”)
public void method1() {}
@synchronised(name=“queue”)
public void method2() {}

Here we have two methods that share the same Mutex so only one thread can execute either of these methods at any points in time.

This would expand to something like this in the compiler

public void method1() {
 Mutex m = new Mutex(‘queue’);
  m.lock();
 …
 m.unlock();
}

public void method2() {
 Mutex m = new Mutex(‘queue’);
  m.lock();
 …
 m.unlock();
}

But what if there were some circumstances where unrelated items could run in parallel. Say we have different regions that don’t interact with each other. Well we could allow variable interpolation in the Mutex naming to use a method argument like this

@synchronised(name=“queue-${region}”)
public void method1(String region) {}

This would expand to

public void method1(String region) {
 Mutex m = new Mutex(String.format(‘queue-$0’, new List<Object>{region}));
  m.lock();
 …
 m.unlock();
}

This would allow access to different regions in parallel but synchronise access to each region

This same annotation could also be allowed on anonymous blocks of code

Hopefully this gives a flavour of the what Salesforce could choose to enable to boost developer productivity if the initial investment in Mutexes was made.

Previous
Previous

SObject Datetime Precision and Testing

Next
Next

Testing Queueable Finalizers Beyond The Limits