Reduce unnecessary QtCore DLL loads during Symbian app thread creation
[qt:qt.git] / src / s60main / newallocator_hook.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Symbian application wrapper of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <e32std.h>
42 #include <qglobal.h>
43
44 #ifdef QT_EXPORTS_NOT_FROZEN
45 // If exports in Qt DLLs are not frozen in this build, then we have to pick up the
46 // allocator creation function by import link. We know the function will be present
47 // in the DLLs we test with, as we have to use the DLLs we have built.
48
49 struct SStdEpocThreadCreateInfo;
50
51 Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo);
52
53
54 /* \internal
55  *
56  * Uses link-time symbol preemption to capture a call from the application
57  * startup. On return, there is some kind of heap allocator installed on the
58  * thread.
59 */
60 TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo)
61 {
62     return qt_symbian_SetupThreadHeap(aNotFirst, aInfo);
63 }
64
65 #else // QT_EXPORTS_NOT_FROZEN
66 // If we are using an export frozen build, it should be compatible with all 4.7.x Qt releases.
67 // We want to use the allocator creation function introduced in qtcore.dll after 4.7.1. But we
68 // can't import link to it, as it may not be present in whatever 4.7.x DLLs we are running with.
69 // So the function is found and called dynamically, by library lookup. If it is not found, we
70 // use the OS allocator creation functions instead.
71
72 #if defined(QT_LIBINFIX)
73 #  define QT_LSTRING2(x) L##x
74 #  define QT_LSTRING(x) QT_LSTRING2(x)
75 #  define QT_LIBINFIX_UNICODE QT_LSTRING(QT_LIBINFIX)
76 #else
77 #  define QT_LIBINFIX_UNICODE L""
78 #endif
79
80 _LIT(QtCoreLibName, "qtcore" QT_LIBINFIX_UNICODE L".dll");
81
82 struct SThreadCreateInfo
83     {
84     TAny* iHandle;
85     TInt iType;
86     TThreadFunction iFunction;
87     TAny* iPtr;
88     TAny* iSupervisorStack;
89     TInt iSupervisorStackSize;
90     TAny* iUserStack;
91     TInt iUserStackSize;
92     TInt iInitialThreadPriority;
93     TPtrC iName;
94     TInt iTotalSize;    // Size including any extras (must be a multiple of 8 bytes)
95     };
96
97 struct SStdEpocThreadCreateInfo : public SThreadCreateInfo
98     {
99     RAllocator* iAllocator;
100     TInt iHeapInitialSize;
101     TInt iHeapMaxSize;
102     TInt iPadding;      // Make structure size a multiple of 8 bytes
103     };
104
105
106 /* \internal
107  *
108  * Uses link-time symbol preemption to capture a call from the application
109  * startup. On return, there is some kind of heap allocator installed on the
110  * thread.
111 */
112 typedef int (*TSetupThreadHeapFunc)(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo);
113 // keep the SetupThreadHeap() pointer so that we don't reload QtCore.dll after the first time
114 static TSetupThreadHeapFunc gp_qt_symbian_SetupThreadHeap = 0;
115 static bool gp_qt_symbian_SetupThreadHeap_set = false;
116
117 TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo)
118 {
119     TInt r = KErrNone;
120
121 #ifndef __WINS__
122     // on first call, aNotFirst will be false.
123     // on second call, gp_qt_symbian_SetupThreadHeap_set will be false(!) because WSD is zeroed after the first call
124     // on subsequent calls, both will be true and we can use the stored SetupThreadHeap() pointer
125     if (aNotFirst && gp_qt_symbian_SetupThreadHeap_set) {
126         if (gp_qt_symbian_SetupThreadHeap)
127             return (*gp_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo);
128     } else {
129         // attempt to create the fast allocator through a known export ordinal in qtcore.dll
130         RLibrary qtcore;
131         gp_qt_symbian_SetupThreadHeap_set = true;
132         if (qtcore.Load(QtCoreLibName) == KErrNone) {
133             const int qt_symbian_SetupThreadHeap_eabi_ordinal = 3713;
134             TLibraryFunction libFunc = qtcore.Lookup(qt_symbian_SetupThreadHeap_eabi_ordinal);
135             if (libFunc) {
136                 TSetupThreadHeapFunc p_qt_symbian_SetupThreadHeap = TSetupThreadHeapFunc(libFunc);
137                 gp_qt_symbian_SetupThreadHeap = p_qt_symbian_SetupThreadHeap;
138                 r = (*p_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo);
139             }
140             qtcore.Close();
141             if (libFunc)
142                 return r;
143         }
144     }
145 #endif
146
147     // no fast allocator support - use default allocator creation
148     if (!aInfo.iAllocator && aInfo.iHeapInitialSize>0)
149         {
150         // new heap required
151         RHeap* pH = NULL;
152         r = UserHeap::CreateThreadHeap(aInfo, pH);
153         }
154     else if (aInfo.iAllocator)
155         {
156         // sharing a heap
157         RAllocator* pA = aInfo.iAllocator;
158         pA->Open();
159         User::SwitchAllocator(pA);
160         r = KErrNone;
161         }
162     return r;
163 }
164
165 #endif // QT_EXPORTS_NOT_FROZEN