46
46
public class Ctags {
47
47
48
48
private static final Logger LOGGER = LoggerFactory .getLogger (Ctags .class );
49
+ private static final long SIGNALWAIT_MS = 5000 ;
49
50
51
+ private final CtagsBuffer buffer = new CtagsBuffer ();
52
+ private final Object syncRoot = new Object ();
53
+ private volatile boolean closing ;
54
+ private volatile boolean signalled ;
50
55
private Process ctags ;
56
+ Thread errThread ;
57
+ Thread outThread ;
51
58
private OutputStreamWriter ctagsIn ;
52
59
private BufferedReader ctagsOut ;
53
60
private static final String CTAGS_FILTER_TERMINATOR = "__ctags_done_with_file__" ;
@@ -77,6 +84,7 @@ public void setCTagsExtraOptionsFile(String CTagsExtraOptionsFile) {
77
84
public void close () throws IOException {
78
85
IOUtils .close (ctagsIn );
79
86
if (ctags != null ) {
87
+ closing = true ;
80
88
LOGGER .log (Level .FINE , "Destroying ctags command" );
81
89
ctags .destroy ();
82
90
}
@@ -292,7 +300,7 @@ private void initialize() throws IOException {
292
300
ctagsIn = new OutputStreamWriter (ctags .getOutputStream ());
293
301
ctagsOut = new BufferedReader (new InputStreamReader (ctags .getInputStream ()));
294
302
295
- Thread errThread = new Thread (new Runnable () {
303
+ errThread = new Thread (new Runnable () {
296
304
297
305
@ Override
298
306
public void run () {
@@ -303,6 +311,7 @@ public void run() {
303
311
while ((s = error .readLine ()) != null ) {
304
312
sb .append (s );
305
313
sb .append ('\n' );
314
+ if (closing ) break ;
306
315
}
307
316
} catch (IOException exp ) {
308
317
LOGGER .log (Level .WARNING , "Got an exception reading ctags error stream: " , exp );
@@ -314,6 +323,34 @@ public void run() {
314
323
});
315
324
errThread .setDaemon (true );
316
325
errThread .start ();
326
+
327
+ outThread = new Thread (() -> {
328
+ while (!closing ) {
329
+ synchronized (syncRoot ) {
330
+ while (!signalled && !closing ) {
331
+ try {
332
+ syncRoot .wait (SIGNALWAIT_MS );
333
+ } catch (InterruptedException e ) {
334
+ LOGGER .log (Level .WARNING ,
335
+ "Ctags direct client unexpectedly interrupted" );
336
+ }
337
+ }
338
+ signalled = false ;
339
+ }
340
+ if (closing ) return ;
341
+
342
+ CtagsReader rdr = new CtagsReader ();
343
+ readTags (rdr );
344
+ Definitions defs = rdr .getDefinitions ();
345
+ try {
346
+ buffer .put (defs );
347
+ } catch (InterruptedException ex ) {
348
+ // ignore
349
+ }
350
+ }
351
+ });
352
+ outThread .setDaemon (true );
353
+ outThread .start ();
317
354
}
318
355
319
356
public Definitions doCtags (String file ) throws IOException {
@@ -338,12 +375,19 @@ public Definitions doCtags(String file) throws IOException {
338
375
339
376
Definitions ret = null ;
340
377
if (file .length () > 0 && !"\n " .equals (file )) {
341
- //log.fine("doing >" + file + "<");
378
+ synchronized (syncRoot ) {
379
+ signalled = true ;
380
+ syncRoot .notify ();
381
+ }
382
+
342
383
ctagsIn .write (file );
343
384
ctagsIn .flush ();
344
- CtagsReader rdr = new CtagsReader ();
345
- readTags (rdr );
346
- ret = rdr .getDefinitions ();
385
+ try {
386
+ ret = buffer .take ();
387
+ } catch (InterruptedException e ) {
388
+ LOGGER .log (Level .WARNING ,
389
+ "Ctags indirect client unexpectedly interrupted" );
390
+ }
347
391
}
348
392
349
393
return ret ;
0 commit comments