xref: /aoo41x/main/pyuno/source/module/pyuno_gc.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #include <pyuno_impl.hxx>
28 #include <osl/thread.hxx>
29 namespace pyuno
30 {
31 
32 bool g_destructorsOfStaticObjectsHaveBeenCalled;
33 class StaticDestructorGuard
34 {
35 public:
36     ~StaticDestructorGuard()
37     {
38         g_destructorsOfStaticObjectsHaveBeenCalled = true;
39     }
40 };
41 StaticDestructorGuard guard;
42 
43 static bool isAfterUnloadOrPy_Finalize()
44 {
45     return g_destructorsOfStaticObjectsHaveBeenCalled ||
46         !Py_IsInitialized();
47 }
48 
49 class GCThread : public ::osl::Thread
50 {
51     PyObject *mPyObject;
52     PyInterpreterState *mPyInterpreter;
53     GCThread( const GCThread & ); // not implemented
54     GCThread &operator =( const GCThread & ); // not implemented
55 
56 public:
57     GCThread( PyInterpreterState *interpreter, PyObject * object );
58     virtual void SAL_CALL run();
59     virtual void SAL_CALL onTerminated();
60 };
61 
62 
63 GCThread::GCThread( PyInterpreterState *interpreter, PyObject * object ) :
64     mPyObject( object ), mPyInterpreter( interpreter )
65 {}
66 
67 void GCThread::run()
68 {
69     //  otherwise we crash here, when main has been left already
70     if( isAfterUnloadOrPy_Finalize() )
71         return;
72     try
73     {
74         PyThreadAttach g( (PyInterpreterState*)mPyInterpreter );
75         {
76             Runtime runtime;
77 
78             // remove the reference from the pythonobject2adapter map
79             PyRef2Adapter::iterator ii =
80                 runtime.getImpl()->cargo->mappedObjects.find( mPyObject );
81             if( ii != runtime.getImpl()->cargo->mappedObjects.end() )
82             {
83                 runtime.getImpl()->cargo->mappedObjects.erase( ii );
84             }
85 
86             Py_XDECREF( mPyObject );
87         }
88     }
89     catch( com::sun::star::uno::RuntimeException & e )
90     {
91         rtl::OString msg;
92         msg = rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
93         fprintf( stderr, "Leaking python objects bridged to UNO for reason %s\n",msg.getStr());
94     }
95 }
96 
97 
98 void GCThread::onTerminated()
99 {
100     delete this;
101 }
102 
103 void decreaseRefCount( PyInterpreterState *interpreter, PyObject *object )
104 {
105     //  otherwise we crash in the last after main ...
106     if( isAfterUnloadOrPy_Finalize() )
107         return;
108 
109     // delegate to a new thread, because there does not seem
110     // to be a method, which tells, whether the global
111     // interpreter lock is held or not
112     // TODO: Look for a more efficient solution
113     osl::Thread *t = new GCThread( interpreter, object );
114     t->create();
115 }
116 
117 }
118