An open API service indexing awesome lists of open source software.

https://github.com/peter-gergely-horvath/threadconfined

ThreadConfinement: enforce thread confinement of objects by wrapping them into guardian proxies
https://github.com/peter-gergely-horvath/threadconfined

Last synced: 4 months ago
JSON representation

ThreadConfinement: enforce thread confinement of objects by wrapping them into guardian proxies

Awesome Lists containing this project

README

        

# Thread Confinement

Thread Confinement - that an object can only be accessed by a single thread - is
an important concept in a multi-threaded application. Finding cases where an
object should be confined to a thread, but it is actually accessed from another
can be tricky.

This library provides support for enforcing thread confinement by wrapping objects
into proxies that fail-fast when accessed from a different thread by throwning an
exception or generating a log message.

## Sample: Thread Confinement guardian in action

The following sample application tries to access `guardedHashSet` from a
different thread it was created from. As a result it will exit with an
exception stack trace similar to the one below:

```
Exception in thread "main" java.lang.RuntimeException: java.util.concurrent.ExecutionException: com.github.threadconfined.ThreadConfinementViolationException: Illegal access from thread 'Thread[pool-1-thread-1,5,main]': object should only be accessed from 'Thread[main,5,main]'
at com.github.threadconfined.SampleApp.launderThrowable(SampleApp.java:40)
at com.github.threadconfined.SampleApp.main(SampleApp.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.util.concurrent.ExecutionException: com.github.threadconfined.ThreadConfinementViolationException: Illegal access from thread 'Thread[pool-1-thread-1,5,main]': object should only be accessed from 'Thread[main,5,main]'
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.github.threadconfined.SampleApp.main(SampleApp.java:25)
... 5 more
Caused by: com.github.threadconfined.ThreadConfinementViolationException: Illegal access from thread 'Thread[pool-1-thread-1,5,main]': object should only be accessed from 'Thread[main,5,main]'
at com.github.threadconfined.ThreadConfinement$ViolationAction$2.onAccessFromUnexpectedThread(ThreadConfinement.java:85)
at com.github.threadconfined.ThreadConfinementGuardianProxy.invoke(ThreadConfinementGuardianProxy.java:32)
at org.javassist.tmp.java.util.HashSet_$$_javassist_0.contains(HashSet_$$_javassist_0.java)
at com.github.threadconfined.SampleApp.lambda$main$0(SampleApp.java:22)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
```

```java
package sample;

import com.github.threadconfined.*;

import java.util.HashSet;
import java.util.concurrent.*;

public class SampleApp {

public static void main(String[] args) {

try {

final HashSet guardedHashSet = ThreadConfinement.threadConfined(new HashSet());

ExecutorService executorService = Executors.newSingleThreadExecutor();

Future futureResult = executorService.submit(() ->
/*
Illegal Access: guardedHashSet was created from main thread,
but is accessed from ExecutorService thread!
*/
guardedHashSet.contains("Foobar"));

futureResult.get();

} catch (InterruptedException e) {
// Unexpected case: interruption -- quit application
} catch (ExecutionException e) {
throw launderThrowable(e);
}
}

private static RuntimeException launderThrowable(Throwable t) {
if (t instanceof java.lang.Error) {
throw (java.lang.Error) t;
} else if (t instanceof RuntimeException) {
return (RuntimeException) t;
} else {
return new RuntimeException(t);
}

}

}

```