2727import java .util .logging .Logger ;
2828
2929/**
30+ * This utility class support locking a thread to a single core, or reserving a whole core for a thread.
31+ *
3032 * @author peter.lawrey
3133 */
3234public class AffinityLock {
@@ -61,6 +63,14 @@ public class AffinityLock {
6163 }
6264 }
6365
66+ /**
67+ * Set the CPU layout for this machine. CPUs which are not mentioned will be ignored.
68+ * <p/>
69+ * Changing the layout will have no impact on thread which have already been assigned.
70+ * It only affects subsequent assignments.
71+ *
72+ * @param cpuLayout for this application to use for this machine.
73+ */
6474 public static void cpuLayout (CpuLayout cpuLayout ) {
6575 synchronized (AffinityLock .class ) {
6676 AffinityLock .cpuLayout = cpuLayout ;
@@ -84,6 +94,9 @@ private static int coreForId(int id) {
8494 return cpuLayout .socketId (id ) * cpuLayout .coresPerSocket () + cpuLayout .coreId (id );
8595 }
8696
97+ /**
98+ * @return The current CpuLayout for the application.
99+ */
87100 public static CpuLayout cpuLayout () {
88101 return cpuLayout ;
89102 }
@@ -95,18 +108,46 @@ private static long getReservedAffinity0() {
95108 return Long .parseLong (reservedAffinity , 16 );
96109 }
97110
111+ /**
112+ * Assign any free cpu to this thread.
113+ *
114+ * @return A handle for the current AffinityLock.
115+ */
98116 public static AffinityLock acquireLock () {
99117 return acquireLock (true );
100118 }
101119
120+ /**
121+ * Assign any free core to this thread.
122+ * <p/>
123+ * In reality, only one cpu is assigned, the rest of the threads for that core are reserved so they are not used.
124+ *
125+ * @return A handle for the current AffinityLock.
126+ */
102127 public static AffinityLock acquireCore () {
103128 return acquireCore (true );
104129 }
105130
131+ /**
132+ * Assign a cpu which can be bound to the current thread or another thread.
133+ * <p/>
134+ * This can be used for defining your thread layout centrally and passing the handle via dependency injection.
135+ *
136+ * @param bind if true, bind the current thread, if false, reserve a cpu which can be bound later.
137+ * @return A handle for an affinity lock.
138+ */
106139 public static AffinityLock acquireLock (boolean bind ) {
107140 return acquireLock (bind , -1 , AffinityStrategies .ANY );
108141 }
109142
143+ /**
144+ * Assign a core(and all its cpus) which can be bound to the current thread or another thread.
145+ * <p/>
146+ * This can be used for defining your thread layout centrally and passing the handle via dependency injection.
147+ *
148+ * @param bind if true, bind the current thread, if false, reserve a cpu which can be bound later.
149+ * @return A handle for an affinity lock.
150+ */
110151 public static AffinityLock acquireCore (boolean bind ) {
111152 return acquireCore (bind , -1 , AffinityStrategies .ANY );
112153 }
@@ -152,6 +193,9 @@ private static AffinityLock acquireCore(boolean bind, int cpuId, AffinityStrateg
152193 }
153194
154195
196+ /**
197+ * @return All the current locks as a String.
198+ */
155199 public static String dumpLocks () {
156200 return dumpLocks0 (LOCKS );
157201 }
@@ -193,10 +237,18 @@ private void assignCurrentThread(boolean bind, boolean wholeCore) {
193237 bind (wholeCore );
194238 }
195239
240+ /**
241+ * Bind the current thread to this reserved lock.
242+ */
196243 public void bind () {
197244 bind (false );
198245 }
199246
247+ /**
248+ * Bind the current thread to this reserved lock.
249+ *
250+ * @param wholeCore if true, also reserve the whole core.
251+ */
200252 public void bind (boolean wholeCore ) {
201253 if (bound && assignedThread != null && assignedThread .isAlive ())
202254 throw new IllegalStateException ("cpu " + id + " already bound to " + assignedThread );
@@ -239,10 +291,19 @@ private boolean canReserve() {
239291 return true ;
240292 }
241293
294+ /**
295+ * Give another affinity lock relative to this one based on a list of strategies.
296+ *
297+ * @param strategies To dertemine if you want the same/different core/socket.
298+ * @return A matching AffinityLock.
299+ */
242300 public AffinityLock acquireLock (AffinityStrategy ... strategies ) {
243301 return acquireLock (false , id , strategies );
244302 }
245303
304+ /**
305+ * Release the current AffinityLock which can be discarded.
306+ */
246307 public void release () {
247308 Thread t = Thread .currentThread ();
248309 synchronized (AffinityLock .class ) {
@@ -262,4 +323,13 @@ public void release() {
262323 }
263324 AffinitySupport .setAffinity (BASE_AFFINITY );
264325 }
326+
327+ @ Override
328+ protected void finalize () throws Throwable {
329+ if (reserved ) {
330+ LOGGER .warning ("Affinity lock for " + assignedThread + " was discarded rather than release()d in a controlled manner." );
331+ release ();
332+ }
333+ super .finalize ();
334+ }
265335}
0 commit comments