Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
Console.cpp
Go to the documentation of this file.
1
2
3#include "Headers/Console.h"
4
8
9#include <iostream>
10
11namespace Divide {
12
14NO_DESTROY vector<Console::ConsolePrintCallbackEntry> Console::s_guiConsoleCallbacks;
15std::ofstream Console::s_logStream;
16std::ofstream Console::s_errorStream;
17
24
26std::atomic_bool Console::s_running = false;
27
28//Use moodycamel's implementation of a concurrent queue due to its "Knock-your-socks-off blazing fast performance."
29//https://github.com/cameron314/concurrentqueue
30namespace
31{
32 NO_DESTROY std::array<Console::OutputEntry, 16> g_outputCache;
33
34 moodycamel::BlockingConcurrentQueue<Console::OutputEntry>& OutBuffer()
35 {
36 NO_DESTROY static moodycamel::BlockingConcurrentQueue<Console::OutputEntry> s_OutputBuffer;
37 return s_OutputBuffer;
38 }
39}
40
41void Console::DecorateAndPrint(std::ostream& outStream, const std::string_view text, const bool newline, const EntryType type) {
43 {
44 outStream << "[ " << std::internal
45 << std::setw(9)
46 << std::setprecision(3)
47 << std::setfill('0')
48 << std::fixed
50 << " ] ";
51 }
52 if ( s_flags & to_base( Flags::DECORATE_FRAME ) ) [[likely]]
53 {
54 outStream << "[ " << GFXDevice::FrameCount() << " ] ";
55 }
56 if ( s_flags & to_base( Flags::DECORATE_THREAD_ID ) ) [[likely]]
57 {
58 outStream << "[ " << std::this_thread::get_id() << " ] ";
59 }
61 {
62 outStream << (type == EntryType::ERR ? " Error: " : " Warning: ");
63 }
64
65 outStream << text;
66
67 if (newline)
68 {
69 outStream << "\n";
70 }
71}
72
73void Console::Output(std::ostream& outStream, const std::string_view text, const bool newline, const EntryType type)
74{
75 if (s_flags & to_base(Flags::ENABLE_OUTPUT) ) [[likely]]
76 {
77 DecorateAndPrint(outStream, text, newline, type);
78 }
79}
80
81void Console::Output(const std::string_view text, const bool newline, const EntryType type)
82{
84 {
85 stringstream outStream;
86 DecorateAndPrint(outStream, text, newline, type);
87
88 const OutputEntry entry
89 {
90 ._text = outStream.str().c_str(),
91 ._type = type
92 };
93
95 {
97 }
98 else if (!OutBuffer().enqueue(entry))
99 {
102 }
103 }
104}
105
107{
108 if ( s_running ) [[likely]]
109 {
110 std::ofstream& outStream = (entry._type == EntryType::ERR && s_flags & to_base( Flags::ENABLE_ERROR_STREAM ) ? s_errorStream : s_logStream );
111 outStream << entry._text.c_str();
112
114 for (const auto& it : s_guiConsoleCallbacks)
115 {
116 if (!s_running)
117 {
118 break;
119 }
120
121 it._cbk(entry);
122 }
123 }
124}
125
127{
128 if ( s_flags & to_base( Flags::ENABLE_OUTPUT ) && s_running) [[likely]]
129 {
130
131 size_t count{};
132 do
133 {
134 count = OutBuffer().try_dequeue_bulk(std::begin(g_outputCache), g_outputCache.size());
135
136 for (size_t i = 0u; i < count; ++i)
137 {
138 PrintToFile(g_outputCache[i]);
139 }
140 } while (count > 0u);
141 }
142}
143
144void Console::Start( const std::string_view logFilePath, const std::string_view erroFilePath, const bool printCopyright ) noexcept
145{
146 s_flags = DEFAULT_FLAGS;
147 s_running.store(true);
148
149 s_logStream = std::ofstream{ (Paths::g_logPath / logFilePath).fileSystemPath(), std::ofstream::out | std::ofstream::trunc };
150 s_errorStream = std::ofstream{ (Paths::g_logPath / erroFilePath).fileSystemPath(), std::ofstream::out | std::ofstream::trunc };
151
152 std::cout.rdbuf( s_logStream.rdbuf() );
153 std::cerr.rdbuf( s_errorStream.rdbuf() );
154
156 if ( printCopyright )
157 {
158 s_logStream << "------------------------------------------------------------------------------\n"
159 << "Copyright (c) 2018 DIVIDE-Studio\n"
160 << "Copyright (c) 2009 Ionut Cava\n\n"
161 << "This file is part of DIVIDE Framework.\n\n"
162 << "Permission is hereby granted, free of charge, to any person obtaining a copy of this software\n"
163 << "and associated documentation files (the 'Software'), to deal in the Software without restriction,\n"
164 << "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\n"
165 << "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\n"
166 << "subject to the following conditions:\n\n"
167 << "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\n"
168 << "THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n"
169 << "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n"
170 << "IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n"
171 << "WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE\n"
172 << "OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
173 << "For any problems or licensing issues I may have overlooked, please contact: \n"
174 << "E-mail: ionut.cava@divide-studio.com | Website: \n http://wwww.divide-studio.com\n"
175 << "-------------------------------------------------------------------------------\n\n";
176 }
177}
178
180{
181 bool expected = true;
182 if ( s_running.compare_exchange_strong(expected, false) )
183 {
184 Flush();
186 s_logStream << "------------------------------------------\n\n\n\n";
187 s_logStream.flush();
188 s_errorStream.flush();
189 std::cerr << std::flush;
190 std::cout << std::flush;
191 }
192}
193
194size_t Console::BindConsoleOutput( const ConsolePrintCallback& guiConsoleCallback )
195{
196 static size_t callbackId{ 0u };
197
199 auto& entry = s_guiConsoleCallbacks.emplace_back();
200 entry._cbk = guiConsoleCallback;
201 entry._id = callbackId++;
202
203 return entry._id;
204}
205
206bool Console::UnbindConsoleOutput( size_t& index )
207{
209
210 const size_t initialSize = s_guiConsoleCallbacks.size();
211 erase_if( s_guiConsoleCallbacks, [index]( const ConsolePrintCallbackEntry& entry )
212 {
213 return entry._id == index;
214 } );
215
216 const bool erased = initialSize > s_guiConsoleCallbacks.size();
217 if ( erased )
218 {
219 index = SIZE_MAX;
220 return true;
221 }
222
223 return false;
224}
225
226} //namespace Divide
227
#define NO_DESTROY
#define DIVIDE_UNEXPECTED_CALL()
static U64 FrameCount() noexcept
Definition: GFXDevice.h:340
D64 ElapsedSeconds() noexcept
NO_DESTROY std::array< Console::OutputEntry, 16 > g_outputCache
Definition: Console.cpp:32
moodycamel::BlockingConcurrentQueue< Console::OutputEntry > & OutBuffer()
Definition: Console.cpp:34
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
std::basic_stringstream< char, std::char_traits< char >, dvd_allocator< char > > stringstream
Definition: STLString.h:43
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
std::shared_mutex SharedMutex
Definition: SharedMutex.h:43
std::shared_lock< mutex > SharedLock
Definition: SharedMutex.h:49
constexpr U32 DEFAULT_FLAGS
Definition: Console.cpp:18
uint32_t U32
Project const SceneEntry & entry
Definition: DefaultScene.h:41
constexpr auto to_base(const Type value) -> Type
Definition: Console.h:126
Definition: Console.h:119
static std::ofstream s_errorStream
Definition: Console.h:153
static std::atomic_bool s_running
Definition: Console.h:157
static void DecorateAndPrint(std::ostream &outStream, std::string_view text, bool newline, EntryType type)
Definition: Console.cpp:41
std::function< void(const OutputEntry &)> ConsolePrintCallback
Definition: Console.h:124
static void PrintToFile(const OutputEntry &entry)
Definition: Console.cpp:106
static vector< ConsolePrintCallbackEntry > s_guiConsoleCallbacks
Definition: Console.h:155
static U32 s_flags
Definition: Console.h:156
static SharedMutex s_callbackLock
Definition: Console.h:154
static void Flush()
Definition: Console.cpp:126
static void Output(std::string_view text, bool newline, EntryType type)
Definition: Console.cpp:81
static bool IsFlagSet(const Flags flag)
Definition: Console.h:140
static bool UnbindConsoleOutput(size_t &index)
Definition: Console.cpp:206
static size_t BindConsoleOutput(const ConsolePrintCallback &guiConsoleCallback)
Definition: Console.cpp:194
static void Start(std::string_view logFilePath, std::string_view erroFilePath, bool printCopyright) noexcept
Definition: Console.cpp:144
static void Stop()
Definition: Console.cpp:179
static std::ofstream s_logStream
Definition: Console.h:152