root/OpenSceneGraph/trunk/src/osg/Notify.cpp @ 10263

Revision 10263, 6.6 kB (checked in by robert, 5 years ago)

From Colin McDonald?, "The latest osg::notify is crashing at initialisation on Solaris, due to
constructor issues:

Within the NullStream? & NotifyStream? classes the base class objects
(ostream) were being initialised before the class member _buffer objects
which they referenced, causing a crash.

I had to move the file scope g_NullStream & g_NotifyStream initialisation
into a function to get them to work.

Also there was a missing osg:: qualifier on getNotifyHandler."

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
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
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/Notify>
14#include <osg/ApplicationUsage>
15#include <osg/ref_ptr>
16#include <string>
17#include <stdlib.h>
18#include <stdio.h>
19#include <sstream>
20#include <iostream>
21
22namespace osg
23{
24
25class NullStreamBuffer : public std::streambuf
26{
27private:
28    std::streamsize xsputn(const std::streambuf::char_type *str, std::streamsize n)
29    {
30        return n;
31    }
32};
33
34struct NullStream : public std::ostream
35{
36public:
37    NullStream():
38        std::ostream(new NullStreamBuffer)
39    { _buffer = dynamic_cast<NullStreamBuffer *>(rdbuf()); }
40       
41    ~NullStream()
42    {
43        rdbuf(0);
44        delete _buffer;
45    }
46
47protected:
48    NullStreamBuffer* _buffer;
49};
50
51/** Stream buffer calling notify handler when buffer is synchronized (usually on std::endl).
52 * Stream stores last notification severity to pass it to handler call.
53 */
54struct NotifyStreamBuffer : public std::stringbuf
55{
56    NotifyStreamBuffer() : _severity(osg::NOTICE)
57    {
58    }
59
60    void setNotifyHandler(osg::NotifyHandler *handler) { _handler = handler; }
61    osg::NotifyHandler *getNotifyHandler() const { return _handler.get(); }
62
63    /** Sets severity for next call of notify handler */
64    void setCurrentSeverity(osg::NotifySeverity severity) { _severity = severity; }
65    osg::NotifySeverity getCurrentSeverity() const { return _severity; }
66
67private:
68
69    int sync()
70    {
71        sputc(0); // string termination
72        if (_handler.valid())
73            _handler->notify(_severity, pbase());
74        pubseekpos(0, std::ios_base::out); // or str(std::string())
75        return 0;
76    }
77
78    osg::ref_ptr<osg::NotifyHandler> _handler;
79    osg::NotifySeverity _severity;
80};
81
82struct NotifyStream : public std::ostream
83{
84public:
85    NotifyStream():
86        std::ostream(new NotifyStreamBuffer)
87    { _buffer = dynamic_cast<NotifyStreamBuffer *>(rdbuf()); }
88
89    void setCurrentSeverity(osg::NotifySeverity severity)
90    {
91        _buffer->setCurrentSeverity(severity);
92    }
93
94    osg::NotifySeverity getCurrentSeverity() const
95    {
96        return _buffer->getCurrentSeverity();
97    }
98       
99    ~NotifyStream()
100    {
101        rdbuf(0);
102        delete _buffer;
103    }
104
105protected:
106    NotifyStreamBuffer* _buffer;
107};
108
109}
110
111using namespace osg;
112
113static osg::ApplicationUsageProxy Notify_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE, "OSG_NOTIFY_LEVEL <mode>", "FATAL | WARN | NOTICE | DEBUG_INFO | DEBUG_FP | DEBUG | INFO | ALWAYS");
114
115static osg::NotifySeverity g_NotifyLevel = osg::NOTICE;
116static osg::NullStream *g_NullStream;
117static osg::NotifyStream *g_NotifyStream;
118
119void osg::setNotifyLevel(osg::NotifySeverity severity)
120{
121    osg::initNotifyLevel();
122    g_NotifyLevel = severity;
123}
124
125
126osg::NotifySeverity osg::getNotifyLevel()
127{
128    osg::initNotifyLevel();
129    return g_NotifyLevel;
130}
131
132void osg::setNotifyHandler(osg::NotifyHandler *handler)
133{
134    osg::NotifyStreamBuffer *buffer = static_cast<osg::NotifyStreamBuffer *>(g_NotifyStream->rdbuf());
135    if (buffer)
136        buffer->setNotifyHandler(handler);
137}
138
139osg::NotifyHandler* osg::getNotifyHandler()
140{
141    osg::initNotifyLevel();
142    osg::NotifyStreamBuffer *buffer = static_cast<osg::NotifyStreamBuffer *>(g_NotifyStream->rdbuf());
143    return buffer ? buffer->getNotifyHandler() : 0;
144}
145
146bool osg::initNotifyLevel()
147{
148    static bool s_NotifyInit = false;
149    static osg::NullStream s_NullStream;
150    static osg::NotifyStream s_NotifyStream;
151
152    if (s_NotifyInit) return true;
153
154    g_NullStream = &s_NullStream;
155    g_NotifyStream = &s_NotifyStream;
156   
157    // g_NotifyLevel
158    // =============
159
160    g_NotifyLevel = osg::NOTICE; // Default value
161
162    char* OSGNOTIFYLEVEL=getenv("OSG_NOTIFY_LEVEL");
163    if (!OSGNOTIFYLEVEL) OSGNOTIFYLEVEL=getenv("OSGNOTIFYLEVEL");
164    if(OSGNOTIFYLEVEL)
165    {
166
167        std::string stringOSGNOTIFYLEVEL(OSGNOTIFYLEVEL);
168
169        // Convert to upper case
170        for(std::string::iterator i=stringOSGNOTIFYLEVEL.begin();
171            i!=stringOSGNOTIFYLEVEL.end();
172            ++i)
173        {
174            *i=toupper(*i);
175        }
176
177        if(stringOSGNOTIFYLEVEL.find("ALWAYS")!=std::string::npos)          g_NotifyLevel=osg::ALWAYS;
178        else if(stringOSGNOTIFYLEVEL.find("FATAL")!=std::string::npos)      g_NotifyLevel=osg::FATAL;
179        else if(stringOSGNOTIFYLEVEL.find("WARN")!=std::string::npos)       g_NotifyLevel=osg::WARN;
180        else if(stringOSGNOTIFYLEVEL.find("NOTICE")!=std::string::npos)     g_NotifyLevel=osg::NOTICE;
181        else if(stringOSGNOTIFYLEVEL.find("DEBUG_INFO")!=std::string::npos) g_NotifyLevel=osg::DEBUG_INFO;
182        else if(stringOSGNOTIFYLEVEL.find("DEBUG_FP")!=std::string::npos)   g_NotifyLevel=osg::DEBUG_FP;
183        else if(stringOSGNOTIFYLEVEL.find("DEBUG")!=std::string::npos)      g_NotifyLevel=osg::DEBUG_INFO;
184        else if(stringOSGNOTIFYLEVEL.find("INFO")!=std::string::npos)       g_NotifyLevel=osg::INFO;
185        else std::cout << "Warning: invalid OSG_NOTIFY_LEVEL set ("<<stringOSGNOTIFYLEVEL<<")"<<std::endl;
186 
187    }
188
189    // Setup standard notify handler
190    osg::NotifyStreamBuffer *buffer = dynamic_cast<osg::NotifyStreamBuffer *>(g_NotifyStream->rdbuf());
191    if (buffer && !buffer->getNotifyHandler())
192        buffer->setNotifyHandler(new StandardNotifyHandler);
193
194    s_NotifyInit = true;
195
196    return true;
197
198}
199
200bool osg::isNotifyEnabled( osg::NotifySeverity severity )
201{
202    return severity<=g_NotifyLevel;
203}
204
205std::ostream& osg::notify(const osg::NotifySeverity severity)
206{
207    static bool initialized = false;
208    if (!initialized)
209    {
210        initialized = osg::initNotifyLevel();
211    }
212
213    if (severity<=g_NotifyLevel)
214    {
215        g_NotifyStream->setCurrentSeverity(severity);
216        return *g_NotifyStream;
217    }
218    return *g_NullStream;
219}
220
221void osg::StandardNotifyHandler::notify(osg::NotifySeverity severity, const char *message)
222{
223    if (severity <= osg::WARN)
224        fputs(message, stderr);
225    else
226        fputs(message, stdout);
227}
228
229#if defined(WIN32) && !defined(__CYGWIN__)
230
231#define WIN32_LEAN_AND_MEAN
232#include <windows.h>
233
234void osg::WinDebugNotifyHandler::notify(osg::NotifySeverity severity, const char *message)
235{
236    OutputDebugStringA(message);
237}
238
239#endif
Note: See TracBrowser for help on using the browser.