aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java
blob: 236ef07544d9e8ac76d5dd14e4096a4456363ea7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package com.jogamp.nativewindow.impl;

import javax.media.nativewindow.*;

//
// Reentrance locking toolkit
// 
public class RecursiveToolkitLock {
    private Thread owner = null;
    private int recursionCount = 0;
    private Exception lockedStack = null;
    private static final long timeout = 3000;  // maximum wait 3s
    private static final boolean TRACE_LOCK = false;

    public Exception getLockedStack() {
        return lockedStack;
    }

    public Thread getOwner() {
        return owner;
    }

    public boolean isOwner() {
        return isOwner(Thread.currentThread());
    }

    public synchronized boolean isOwner(Thread thread) {
        return owner == thread ;
    }

    public synchronized boolean isLocked() {
        return null != owner;
    }

    public synchronized int getRecursionCount() {
        return recursionCount;
    }

    public synchronized void validateLocked() {
        if ( !isLocked() ) {
            throw new RuntimeException(Thread.currentThread()+": Not locked");
        }
        if ( !isOwner() ) {
            getLockedStack().printStackTrace();
            throw new RuntimeException(Thread.currentThread()+": Not owner, owner is "+owner);
        }
    }

    /** Recursive and blocking lockSurface() implementation */
    public synchronized void lock() {
        Thread cur = Thread.currentThread();
        if(TRACE_LOCK) {
            System.out.println("... LOCK 0 ["+this+"], recursions "+recursionCount+", "+cur);
        }
        if (owner == cur) {
            ++recursionCount;
            if(TRACE_LOCK) {
                System.out.println("+++ LOCK 1 ["+this+"], recursions "+recursionCount+", "+cur);
            }
            return;
        }

        long ts = System.currentTimeMillis();
        while (owner != null && (System.currentTimeMillis()-ts) < timeout) {
            try {
                wait(timeout);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        if(owner != null) {
            lockedStack.printStackTrace();
            throw new RuntimeException("Waited "+timeout+"ms for: "+owner+" - "+cur+", with recursionCount "+recursionCount+", lock: "+this);
        }
        if(TRACE_LOCK) {
            System.out.println("+++ LOCK X ["+this+"], recursions "+recursionCount+", "+cur);
        }
        owner = cur;
        lockedStack = new Exception("Previously locked by "+owner+", lock: "+this);
    }
    

    /** Recursive and unblocking unlockSurface() implementation */
    public synchronized void unlock() {
        unlock(null);
    }

    /** Recursive and unblocking unlockSurface() implementation */
    public synchronized void unlock(Runnable taskAfterUnlockBeforeNotify) {
        validateLocked();

        if (recursionCount > 0) {
            --recursionCount;
            if(TRACE_LOCK) {
                System.out.println("--- LOCK 1 ["+this+"], recursions "+recursionCount+", "+Thread.currentThread());
            }
            return;
        }
        owner = null;
        lockedStack = null;
        if(null!=taskAfterUnlockBeforeNotify) {
            taskAfterUnlockBeforeNotify.run();
        }
        if(TRACE_LOCK) {
            System.out.println("--- LOCK X ["+this+"], recursions "+recursionCount+", "+Thread.currentThread());
        }
        notifyAll();
    }
}