1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
|
=== Stones of Nvwa ===
The Name
Nvwa ("v" is pronounced like the French "u"), is one of the most
ancient Chinese goddesses. She was said to have created human beings,
and, when the evil god Gong-gong crashed himself upon one of the
pillars that support the sky and made a hole in it, she mended the sky
with five-coloured stones.
I thought of the name Nvwa by analogy with Loki. Since it is so small
a project and it contains utilities instead of a complete framework, I
think "stones" a good metaphor.
Code Organization
Nvwa versions prior to 1.0 did not use a namespace. It looked to me
overkill to use a namespace in this small project. However, having
had more project experience and seen more good examples, I have
changed my mind. All nvwa functions and global variables are now
inside the namespace "nvwa".
This said, I do not want to break backward compatibility abruptly.
First, people are still able to disable the namespace by defining the
macro NVWA_USE_NAMESPACE to 0 (not really recommended, though).
Second, I still use the quotation mark (") to include header files
internally so that old users do not have to change the include
directory (again, not recommended and intended to help the transition
only). Third, I have not changed most of the macro names -- that
would break existing code and could do more harm than good now. In
addition, I am not a fan of macro prefixes anyway.
Overall, I am quite happy with the changes: some code is simplified,
and in many cases I do not have to use the uglified names to avoid
potential name conflicts. The changes also do not mean anything to
new users. You just need to follow the modern C++ way. You should
add the root directory of this project to your include directory
(there should be a "nvwa" directory inside it with the source files).
To include the header file, use "#include <nvwa/...>".
Contents
A brief introduction follows. Check the Doxygen documentation for
more (technical) details.
* boolarray.cpp
* boolarray.h
A replacement of std::vector<bool>. I wrote it before I knew of
vector<bool>, or I might not have written it at all. However, it is
faster than many vector<bool> implementations (your mileage may
vary), and it has members like at, set, reset, flip, and count. I
personally find "count" very useful.
* c++11.h
Detection macros for certain features of C++11 that might be of
interest to code/library writers. I have used existing online
resources, and I have tested them on popular platforms and compilers
that I have access to (Windows, OS X, and Linux; MSVC, Clang, and
GCC), but of course not all versions or all combinations. Patches
are welcome for corrections and amendments.
* class_level_lock.h
The Loki ClassLevelLockable adapted to use the fast_mutex layer. One
minor divergence from Loki is that the template has an additional
template parameter _RealLock to boost the performance in non-locking
scenarios. Unless HAVE_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION is
explicitly defined to 0, this is enabled automatically. Cf.
object_level_lock.h.
* cont_ptr_utils.h
Utility functors for containers of pointers adapted from Scott Meyers'
Effective STL.
* debug_new.cpp
* debug_new.h
A cross-platform, thread-safe memory leak detector. It is a
light-weight one designed only to catch unmatched pairs of
new/delete. I know there are already many existing memory leak
detectors, but as far as I know, free solutions are generally slow,
memory-consuming, and quite complicated to use. This solution is
very easy to use, and has very low space/time overheads. Just link
in debug_new.cpp for leakage report, and include debug_new.h for
additional file/line information. It will automatically switch on
multi-threading when the appropriate option of a recognized compiler
is specified. Check fast_mutex.h for more threading details.
Special support for gcc/binutils has been added to debug_new lately.
Even if the header file debug_new.h is not included, or
_DEBUG_NEW_REDEFINE_NEW is defined to 0 when it is included,
file/line information can be displayed if debugging symbols are
present in the executable, since debug_new stores the caller
addresses of memory allocation/deallocation routines and they will be
converted with addr2line (or atos on a Mac) on the fly. This makes
memory tracing much easier.
NOTE for Mac OS X users: If you use OS X 10.7 or later, you may need
to add "-Wl,-no_pie" at the end of the command line. By default OS X
will now create position-independent executables (PIE), and the OS
will load a PIE at a random address each time it is executed, making
it difficult to convert the address to symbols. (I Googled a while
for a way to get the base address of a process, but could not find
working code. If you know how to do it right, drop me a message.)
With an idea from Greg Herlihy's post in comp.lang.c++.moderated, the
implementation was much improved in 2007. The most significant
result is that placement new can be used with debug_new now! Full
support for new(std::nothrow) is provided, with its null-returning
error semantics (by default). Memory corruption will be checked on
freeing the pointers and checking the leaks, and a new function
check_mem_corruption is added for your on-demand use in debugging.
You may also want to define _DEBUG_NEW_TAILCHECK to something like 4
for past-end memory corruption check, which is off by default to
ensure performance is not affected.
An article on its design and implementation is available at
http://nvwa.sourceforge.net/article/debug_new.htm
* fast_mutex.h
The threading transparent layer simulating a non-recursive mutex. It
supports C++11 mutex, POSIX mutex, and Win32 critical section, as
well as a no-threads mode. Unlike Loki and some other libraries,
threading mode is not to be specified in code, but detected from the
environment. It will automatically switch on multi-threading mode
(inter-thread exclusion) when the "-MT"/"-MD" option of MSVC, the
"-mthreads" option of MinGW GCC, or the "-pthread" option of GCC
under POSIX environments, is used. One advantage of the current
implementation is that the construction and destruction of a static
object using a static fast_mutex not yet constructed or already
destroyed are allowed to work (with lock/unlock operations ignored),
and there are re-entry checks for lock/unlock operations when the
preprocessing symbol _DEBUG is defined.
* fc_queue.h
A queue that has a fixed capacity (maximum number of allowed items).
All memory is pre-allocated when the queue is initialized, so memory
consumption is well controlled. When the queue is full, inserting a
new item will discard the oldest item in the queue. Care is taken to
ensure this class template provides the strong exception safety
guarantee.
This class template is a good exercise for me to make a STL-type
container. Depending on your needs, you may find circular_buffer in
Boost more useful, which provides similar functionalities and a
richer API. However, the design philosophies behind the two
implementations are quite different. fc_queue is modelled closely on
std::queue, and I optimize mainly for a lockless producer-consumer
pattern -- when there is one producer and one consumer, and the
producer does not try to queue an element when the queue is already
full, no lock is needed for the queue operations.
* file_line_reader.cpp
* file_line_reader.h
This is one of the line reading classes I implemented modelling the
Python approach. They make reading lines from a file a simple loop.
This specific class allows reading from a traditional FILE*.
Cf. istream_line_reader.h and mmap_line_reader.h.
See the following blog for the motivation and example code:
https://yongweiwu.wordpress.com/2016/11/12/performance-of-my-line-readers/
* fixed_mem_pool.h
A memory pool implementation that requires initialization (allocates
a fixed-size chunk) prior to its use. It is simple and makes no
memory fragmentation, but the memory pool size cannot be changed
after initialization. Macros are provided to easily make a class use
pooled new/delete.
* functional.h
This is my test bed for functional programming. If you are into
functional programming, check it out. It includes functional
programming patterns like:
- map
- reduce
- compose
- fixed-point combinator
- curry
- optional
My blogs on functional programming may be helpful:
https://yongweiwu.wordpress.com/2014/12/07/study-notes-functional-programming-with-cplusplus/
https://yongweiwu.wordpress.com/2014/12/14/y-combinator-and-cplusplus/
https://yongweiwu.wordpress.com/2014/12/29/type-deduction-and-my-reference-mistakes/
https://yongweiwu.wordpress.com/2015/01/03/generic-lambdas-and-the-compose-function/
* istream_line_reader.h
This is one of the line reading classes I implemented modelling the
Python approach. They make reading lines from a file a simple loop.
This specific class allows reading from an input stream.
Cf. file_line_reader.h and mmap_line_reader.h.
See the following blogs for the motivation and example code:
https://yongweiwu.wordpress.com/2016/08/16/python-yield-and-cplusplus-coroutines/
https://yongweiwu.wordpress.com/2016/11/12/performance-of-my-line-readers/
* mem_pool_base.cpp
* mem_pool_base.h
A class solely to be inherited by memory pool implementations. It is
used by static_mem_pool and fixed_mem_pool.
* mmap_line_reader.cpp
* mmap_line_reader.h
This is one of the line reading classes I implemented modelling the
Python approach. They make reading lines from a file a simple loop.
This specific class allows reading from an on-disk file via memory-
mapped file I/O. Cf. istream_line_reader.h and file_line_reader.h.
See the following blog for the motivation and example code:
https://yongweiwu.wordpress.com/2016/11/12/performance-of-my-line-readers/
* object_level_lock.h
The Loki ObjectLevelLockable adapted to use the fast_mutex layer.
The member function get_locked_object does not exist in Loki, but is
also taken from Mr Alexandrescu's article. Cf. class_level_lock.h.
* pctimer.h
A function to get a high-resolution timer for Win32/Cygwin/Unix. It
is quite useful for measurement and optimization.
* set_assign.h
Utility routines to make up for the fact that STL only has set_union
(+) and set_difference (-) algorithms but no corresponding += and -=
operations available.
* static_mem_pool.cpp
* static_mem_pool.h
A memory pool implementation to pool memory blocks according to
compile-time block sizes. Macros are provided to easily make a class
use pooled new/delete.
An article on its design and implementation is available at
http://nvwa.sourceforge.net/article/static_mem_pool.htm
* tree.h
A generic tree class template along with traversal utilities.
Besides the usual template argument of value type, it has an
additional argument of storage policy, which can be either unique or
shared. Traversal utility classed are provided so that traversing a
tree can be simply done in a range-based for loop. The test code,
test/test_tree.cpp, shows its basic usage.
* type_traits.h
This file was separated from fc_queue.h. Type traits were not
standardized until C++11, and, in addition, there were late changes
in the trait names that did not go into even the 2012 releases of
MSVC and GCC. So I made a nvwa::is_trivially_destructible that can
work across main compilers.
In the post-C++11 world, this is no longer useful. Use of this file
is deprecated.
$Id: README,v 1.1 2017/03/29 14:08:55 adah Exp $
vim:autoindent:expandtab:formatoptions=tcqlm:textwidth=72:
|