mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-5: Implement thread-safe automatic cleanup of a group of shared objects.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.sharing;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Provides thread-safe registration and cleanup of a growing set of objects.
|
||||
* Each SharedObjectManager can track arbitrarily-many objects, each registered
|
||||
* with the register() function. A SharedObjectManager tracks objects until it
|
||||
* is invalidated, after which all registered objects are cleaned up. Attempts
|
||||
* to register new objects after the SharedObjectManager has been invalidated
|
||||
* will cause the provided object to be immediately cleaned up.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @param <T>
|
||||
* The type of object managed by this SharedObjectManager.
|
||||
*/
|
||||
public abstract class SharedObjectManager<T> {
|
||||
|
||||
/**
|
||||
* Whether this SharedObjectManager has been invalidated.
|
||||
*/
|
||||
private final AtomicBoolean invalidated = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* The collection of all objects being tracked by this SharedObjectManager.
|
||||
*/
|
||||
private final Queue<T> objects = new ConcurrentLinkedQueue<T>();
|
||||
|
||||
/**
|
||||
* Cleans up the given object. This function is invoked exactly once on all
|
||||
* tracked objects after invalidate() is called, and exactly once for any
|
||||
* call to register() which occurs after invalidate() was called.
|
||||
*
|
||||
* @param object
|
||||
* The object to cleanup.
|
||||
*/
|
||||
protected abstract void cleanup(T object);
|
||||
|
||||
/**
|
||||
* Invokes the cleanup() function on all tracked objects, removing each
|
||||
* object from the underlying collection. It is guaranteed that cleanup()
|
||||
* will be invoked only once for each object, even if multiple calls to
|
||||
* cleanupAll() are running concurrently, and that the underlying collection
|
||||
* will be empty after all calls to cleanupAll() complete.
|
||||
*/
|
||||
private void cleanupAll() {
|
||||
|
||||
T current;
|
||||
|
||||
// Remove all objects from underlying collection, cleaning up each
|
||||
// object individually
|
||||
while ((current = objects.poll()) != null)
|
||||
cleanup(current);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given object with this SharedObjectManager such that it is
|
||||
* cleaned up once the SharedObjectManager is invalidated. If the
|
||||
* SharedObjectManager has already been invalidated, the object will be
|
||||
* cleaned up immediately.
|
||||
*
|
||||
* @param object
|
||||
* The object to register with this SharedObjectManager.
|
||||
*/
|
||||
public void register(T object) {
|
||||
|
||||
// If already invalidated (or invalidation is in progress), avoid adding
|
||||
// the object unnecessarily - just cleanup now
|
||||
if (invalidated.get()) {
|
||||
cleanup(object);
|
||||
return;
|
||||
}
|
||||
|
||||
// Store provided object
|
||||
objects.add(object);
|
||||
|
||||
// If collection was invalidated while object was being added, recheck
|
||||
// the underlying collection and cleanup
|
||||
if (invalidated.get())
|
||||
cleanupAll();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates this SharedObjectManager, cleaning up any registered objects
|
||||
* and preventing future registration of objects. If attempts to register
|
||||
* objects are made after this function is invoked, those objects will be
|
||||
* immediately cleaned up.
|
||||
*/
|
||||
public void invalidate() {
|
||||
|
||||
// Mark collection as invalidated, but do not bother cleaning up if
|
||||
// already invalidated
|
||||
if (!invalidated.compareAndSet(false, true))
|
||||
return;
|
||||
|
||||
// Clean up all stored objects
|
||||
cleanupAll();
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user