Skip to content

Instantly share code, notes, and snippets.

@abdolence
Last active February 27, 2020 16:10
Show Gist options
  • Save abdolence/18aadcccf4c16f8a1b10b2a6433d4f8a to your computer and use it in GitHub Desktop.
Save abdolence/18aadcccf4c16f8a1b10b2a6433d4f8a to your computer and use it in GitHub Desktop.
/**
* A stateful implementation of an auto-closable lock/monitor
* for the specified lockwith an ability to unlock it preliminarily.
* The class philosophy and namings are borrowed from C++ std::unique_lock<>.
*
* @apiNote this class isn't reentrant and isn't supposed to be shared across threads
* or to be used as a field.
* The instances of this class should be used as
* stack/method local variables with try-with-resources.
*/
public final class UniqueLockMonitor implements AutoCloseable {
private boolean locked;
private final Lock lock;
/**
* Private constructor to initialise a monitor
*
* @param lock underlying lock
* @param locked the current lock status
*/
private UniqueLockMonitor(final Lock lock, final boolean locked) {
assert lock != null;
this.lock = lock;
this.locked = locked;
}
/**
* Lock and create a monitor on the specified lock
*
* @param lock a lock
* @return a monitor instance on the specified lock
*/
public static UniqueLockMonitor lockAndMonitor(final Lock lock) {
final UniqueLockMonitor result = new UniqueLockMonitor(lock, false);
result.lock();
return result;
}
/**
* Lock manually.
*
* @apiNote Consequent multiple locks aren't allowed
* to avoid mistakes and sharing monitor instances.
*/
void lock() {
assert !this.locked;
lock.lock();
this.locked = true;
}
/**
* Unlock manually.
*
* @apiNote Consequent multiple unlocks aren't allowed
* to avoid mistakes and sharing monitor instances.
*/
void unlock() {
assert this.locked;
lock.unlock();
this.locked = false;
}
@Override
public void close() {
if (this.locked) {
unlock();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment