# Copyright (c) 2013 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
# Copyright (c) 2013 Centre national de la recherche scientifique (CNRS)
# Copyright (c) 2020 Simons Foundation
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You may obtain a copy of the License at
# https:#www.gnu.org/licenses/gpl-3.0.txt
#
# Authors: Olivier Parcollet, Nils Wentzell
import threading, time, sys, os, fcntl
__all__ = ['start_redirect', 'stop_redirect']
# A thread that will redirect the c++ stdout to the ipython notebook
[docs]
class T(threading.Thread):
[docs]
def __init__(self):
threading.Thread.__init__(self)
self.go_on = True
# copy the c++ stdout handler for later
self.oldhandle = os.dup(1)
[docs]
def stop(self):
self.go_on = False
[docs]
def run(self):
# create a pipe and glue the c++ stdout to its write end
# make the read end non-blocking
piper, pipew = os.pipe()
os.dup2(pipew, 1)
os.close(pipew)
fcntl.fcntl(piper,fcntl.F_SETFL,os.O_NONBLOCK)
while self.go_on:
# give the system 1 second to fill up the pipe
time.sleep(1)
try:
# read out the pipe and write it to the screen
# if the pipe was empty it return an error (hence the try-except)
sys.stdout.write(os.read(piper, 10000))
sys.stdout.flush()
except:
pass
# when we want to stop the thread put back the c++ stdout where it was
# clear the pipe
os.dup2(self.oldhandle, 1)
os.close(piper)
return
# flag to know if the thread was started
started = False
# start the redirection
[docs]
def start_redirect():
global started
global a
if started:
print("Already redirected c++ output")
else:
started = True
# start a new redirection thread
a = T()
a.start()
# stop the redirection
[docs]
def stop_redirect():
global started
global a
if started:
started = False
a.stop()