Skip to content

Commit 6a288ba

Browse files
Merge pull request #670 from matthiasblaesing/simple_com_thread
Reintroduce ComThread and move base functions into ObjectFactory
2 parents 494959b + bcf57cd commit 6a288ba

18 files changed

+1037
-240
lines changed

Diff for: contrib/platform/src/com/sun/jna/platform/win32/COM/util/CallbackProxy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public class CallbackProxy implements IDispatchCallback {
5555
private static float DEFAULT_FLOAT;
5656
private static double DEFAULT_DOUBLE;
5757

58-
public CallbackProxy(Factory factory, Class<?> comEventCallbackInterface,
58+
public CallbackProxy(ObjectFactory factory, Class<?> comEventCallbackInterface,
5959
IComEventCallbackListener comEventCallbackListener) {
6060
this.factory = factory;
6161
this.comEventCallbackInterface = comEventCallbackInterface;
@@ -65,7 +65,7 @@ public CallbackProxy(Factory factory, Class<?> comEventCallbackInterface,
6565
this.dispatchListener = new DispatchListener(this);
6666
}
6767

68-
Factory factory;
68+
ObjectFactory factory;
6969
Class<?> comEventCallbackInterface;
7070
IComEventCallbackListener comEventCallbackListener;
7171
REFIID listenedToRiid;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/* Copyright (c) 2014 Dr David H. Akehurst (itemis), All Rights Reserved
2+
*
3+
* This library is free software; you can redistribute it and/or
4+
* modify it under the terms of the GNU Lesser General Public
5+
* License as published by the Free Software Foundation; either
6+
* version 2.1 of the License, or (at your option) any later version.
7+
*
8+
* This library is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
* Lesser General Public License for more details.
12+
*/
13+
package com.sun.jna.platform.win32.COM.util;
14+
15+
import java.lang.Thread.UncaughtExceptionHandler;
16+
import java.util.concurrent.Callable;
17+
import java.util.concurrent.ExecutionException;
18+
import java.util.concurrent.ExecutorService;
19+
import java.util.concurrent.Executors;
20+
import java.util.concurrent.ThreadFactory;
21+
import java.util.concurrent.TimeUnit;
22+
import java.util.concurrent.TimeoutException;
23+
24+
import com.sun.jna.platform.win32.Ole32;
25+
import com.sun.jna.platform.win32.WinNT;
26+
import com.sun.jna.platform.win32.COM.COMUtils;
27+
28+
public class ComThread {
29+
private static ThreadLocal<Boolean> isCOMThread = new ThreadLocal<Boolean>();
30+
31+
ExecutorService executor;
32+
Runnable firstTask;
33+
boolean requiresInitialisation;
34+
long timeoutMilliseconds;
35+
UncaughtExceptionHandler uncaughtExceptionHandler;
36+
37+
public ComThread(final String threadName, long timeoutMilliseconds, UncaughtExceptionHandler uncaughtExceptionHandler) {
38+
this(threadName, timeoutMilliseconds, uncaughtExceptionHandler, Ole32.COINIT_MULTITHREADED);
39+
}
40+
41+
public ComThread(final String threadName, long timeoutMilliseconds, UncaughtExceptionHandler uncaughtExceptionHandler, final int coinitialiseExFlag) {
42+
this.requiresInitialisation = true;
43+
this.timeoutMilliseconds = timeoutMilliseconds;
44+
this.uncaughtExceptionHandler = uncaughtExceptionHandler;
45+
this.firstTask = new Runnable() {
46+
@Override
47+
public void run() {
48+
try {
49+
//If we do not use COINIT_MULTITHREADED, it is necessary to have
50+
// a message loop see -
51+
// [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5529/Understanding-COM-Apartments-Part-I.htm]
52+
// [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5533/Understanding-COM-Apartments-Part-II.htm]
53+
WinNT.HRESULT hr = Ole32.INSTANCE.CoInitializeEx(null, coinitialiseExFlag);
54+
isCOMThread.set(true);
55+
COMUtils.checkRC(hr);
56+
ComThread.this.requiresInitialisation = false;
57+
} catch (Throwable t) {
58+
ComThread.this.uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), t);
59+
}
60+
}
61+
};
62+
executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
63+
64+
@Override
65+
public Thread newThread(Runnable r) {
66+
if (!ComThread.this.requiresInitialisation) {
67+
// something has gone wrong!
68+
throw new RuntimeException("ComThread executor has a problem.");
69+
}
70+
Thread thread = new Thread(r, threadName);
71+
//make sure this is a daemon thread, or it will stop JVM existing
72+
// if program does not call terminate();
73+
thread.setDaemon(true);
74+
75+
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
76+
@Override
77+
public void uncaughtException(Thread t, Throwable e) {
78+
ComThread.this.requiresInitialisation = true;
79+
ComThread.this.uncaughtExceptionHandler.uncaughtException(t, e);
80+
}
81+
});
82+
83+
return thread;
84+
}
85+
});
86+
87+
}
88+
89+
/**
90+
* Stop the COM Thread.
91+
*
92+
* @param timeoutMilliseconds
93+
* number of milliseconds to wait for a clean shutdown before a
94+
* forced shutdown is attempted
95+
*/
96+
public void terminate(long timeoutMilliseconds) {
97+
try {
98+
99+
executor.submit(new Runnable() {
100+
@Override
101+
public void run() {
102+
Ole32.INSTANCE.CoUninitialize();
103+
}
104+
}).get(timeoutMilliseconds, TimeUnit.MILLISECONDS);
105+
106+
executor.shutdown();
107+
108+
} catch (InterruptedException e) {
109+
e.printStackTrace();
110+
} catch (ExecutionException e) {
111+
e.printStackTrace();
112+
} catch (TimeoutException e) {
113+
executor.shutdownNow();
114+
}
115+
}
116+
117+
@Override
118+
protected void finalize() throws Throwable {
119+
if (!executor.isShutdown()) {
120+
this.terminate(100);
121+
}
122+
}
123+
124+
static void setComThread(boolean value) {
125+
isCOMThread.set(value);
126+
}
127+
128+
public <T> T execute(Callable<T> task) throws TimeoutException, InterruptedException, ExecutionException {
129+
// If the call is done on a COM thread, invoke directly
130+
// if the call comes from outside the invokation is dispatched
131+
// into the Dispatch Thread.
132+
Boolean comThread = isCOMThread.get();
133+
if(comThread == null) {
134+
comThread = false;
135+
}
136+
if(comThread) {
137+
try {
138+
return task.call();
139+
} catch (Exception ex) {
140+
throw new ExecutionException(ex);
141+
}
142+
} else {
143+
if (this.requiresInitialisation) {
144+
executor.execute(firstTask);
145+
}
146+
return executor.submit(task).get(this.timeoutMilliseconds, TimeUnit.MILLISECONDS);
147+
}
148+
}
149+
150+
}

Diff for: contrib/platform/src/com/sun/jna/platform/win32/COM/util/Convert.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public static VARIANT toVariant(Object value) {
133133
}
134134
}
135135

136-
public static Object toJavaObject(VARIANT value, Class<?> targetClass, Factory factory, boolean addReference, boolean freeValue) {
136+
public static Object toJavaObject(VARIANT value, Class<?> targetClass, ObjectFactory factory, boolean addReference, boolean freeValue) {
137137
if (null==value
138138
|| value.getVarType().intValue() == VT_EMPTY
139139
|| value.getVarType().intValue() == VT_NULL) {

Diff for: contrib/platform/src/com/sun/jna/platform/win32/COM/util/EnumMoniker.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
package com.sun.jna.platform.win32.COM.util;
1414

1515
import java.util.Iterator;
16-
import java.util.concurrent.Callable;
17-
import java.util.concurrent.ExecutionException;
18-
import java.util.concurrent.TimeoutException;
1916

2017
import com.sun.jna.platform.win32.WinDef;
2118
import com.sun.jna.platform.win32.WinNT;
@@ -36,7 +33,7 @@
3633
public class EnumMoniker implements Iterable<IDispatch> {
3734

3835
protected EnumMoniker(IEnumMoniker raw, com.sun.jna.platform.win32.COM.IRunningObjectTable rawRot,
39-
Factory factory) {
36+
ObjectFactory factory) {
4037

4138
assert COMUtils.comIsInitialized() : "COM not initialized";
4239

@@ -50,7 +47,7 @@ protected EnumMoniker(IEnumMoniker raw, com.sun.jna.platform.win32.COM.IRunningO
5047
this.cacheNext();
5148
}
5249

53-
Factory factory;
50+
ObjectFactory factory;
5451
com.sun.jna.platform.win32.COM.IRunningObjectTable rawRot;
5552
IEnumMoniker raw;
5653
Moniker rawNext;

0 commit comments

Comments
 (0)