Need help with nvwa?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

adah1972
144 Stars 45 Forks zlib License 577 Commits 0 Opened issues

Description

My small collection of C++ utilities

Services available

!
?

Need anything else?

Contributors list

# 106,178
Shell
C
c-plus-...
thread-...
577 commits
                     === 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 supported 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 changed my mind. All nvwa functions and global variables were moved into the namespace "nvwa".

This said, I did not want to break backward compatibility abruptly. First, people are still able to disable the namespace by defining the macro NVWAUSENAMESPACE to 0 (not really recommended, though). Second, I still used 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 did not change 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.

The changes 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 ".

Contents

A brief introduction follows. Check the Doxygen documentation for more (technical) details.

  • boolarray.cpp
  • boolarray.h

A replacement of std::vector. I wrote it before I knew of vector, or I might not have written it at all. However, it is faster than many vector implementations (your mileage may vary), and it has members like at, set, reset, flip, and count. I personally find "count" very useful.

  • c++_features.h

Detection macros for certain modern C++ features 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, Linux, and macOS; MSVC, GCC, and Clang), but of course not all versions or all combinations. Patches are welcome for corrections and amendments.

  • classlevellock.h

The Loki ClassLevelLockable adapted to use the fastmutex layer. One minor divergence from Loki is that the template has an additional template parameter _RealLock to boost the performance in non-locking scenarios. Cf. objectlevel_lock.h.

  • contptrutils.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 debugnew.cpp for leakage report, and include debugnew.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 debugnew lately. Even if the header file debugnew.h is not included, or DEBUGNEWREDEFINENEW 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 macOS) on the fly. This makes memory tracing much easier.

NOTE for Linux/macOS users: Nowadays GCC and Clang create position- independent executables (PIE) by default so that the OS can apply address space layout randomization (ASLR), loading a PIE at a random address each time it is executed and making it difficult to convert the address to symbols. The simple solution is to use the command-line option "-no-pie" on Linux, or "-Wl,-no_pie" on macOS.

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 debugnew 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 checkmemcorruption is added for your on-demand use in debugging. You may also want to define _DEBUGNEW_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 circularbuffer in Boost more useful, which provides similar functionalities and a richer API. However, the design philosophies behind the two implementations are quite different. fcqueue 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.

I have recently also switched to using C++11 atomic variables in fc_queue. Previously the code worked for me, but at least theoretically it was not safe: compilers may optimize the code in unexpected ways, and multiple processors may cause surprises too. There is a problem after the change, though. Using the old interface is not optimal now in the producer-consumer scenario, and two new read/write functions are provided to make it work more efficiently.

  • filelinereader.cpp
  • filelinereader.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 implementation allows reading from a traditional FILE*. Cf. istreamlinereader.h, mmapbytereader.h, and mmaplinereader.h.

See the following blog for the motivation and example code:

https://tinyurl.com/cpp-line-readers

  • fixedmempool.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://tinyurl.com/cpp-functional-notes https://tinyurl.com/cpp-y-combinator https://tinyurl.com/cpp-type-deduction https://tinyurl.com/generic-lambdas-compose

  • istreamlinereader.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 implementation allows reading from an input stream. Cf. filelinereader.h and mmaplinereader.h.

See the following blogs for the motivation and example code:

https://tinyurl.com/cpp-coroutines https://tinyurl.com/cpp-line-readers

  • mempoolbase.cpp
  • mempoolbase.h

A class solely to be inherited by memory pool implementations. It is used by staticmempool and fixedmempool.

  • mmapbytereader.h

This file contains the byte reading class template I implemented modelling the Python approach. It makes reading characters from a file a simple loop. This implementation uses memory-mapped file I/O. Cf. mmaplinereader.h.

  • mmaplinereader.h

This file contains the line reading class template I implemented modelling the Python approach. It makes reading lines from a file a simple loop. This implementation uses memory-mapped file I/O. Cf. istreamlinereader.h, filelinereader.h, and mmapbytereader.h.

See the following blogs for the motivation and example code:

https://tinyurl.com/cpp-line-readers https://tinyurl.com/mmap-string-view

  • mmaplineview.h

A mmaplineview is similar to mmaplinereadersv defined in mmapline_reader.h, but it has gone an extra mile to satisfy the View concept (to be introduced in C++20). It can be trivially copied.

  • mmapreaderbase.cpp
  • mmapreaderbase.h

A class that wraps the difference of memory-mapped file I/O between Unix and Windows. It is used by mmapbytereader and mmaplinereader.

  • objectlevellock.h

The Loki ObjectLevelLockable adapted to use the fastmutex layer. The member function getlockedobject does not exist in Loki, but is also taken from Mr Alexandrescu's article. Cf. classlevel_lock.h.

  • pctimer.h

A function to get a high-resolution timer for Win32/Cygwin/Unix. It is useful for measurement and optimization, and remains easier to use than std::chrono::highresolutionclock after the advent of C++11.

  • set_assign.h

Utility routines to make up for the fact that STL only has setunion (+) and setdifference (-) algorithms but no corresponding += and -= operations available.

  • split.h

Implementation of a split routine that allows efficient and lazy split of a string (or stringview). It takes advantage of the C++17 stringview, and the split result can be either used on the fly or returned as a vector.

While the ranges library provides a similar function, it does not yet use string_view, and compiling with ranges is typically much slower -- of course, it is much more powerful as well.

  • staticmempool.cpp
  • staticmempool.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/staticmempool.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.

vim:autoindent:expandtab:formatoptions=tcqlm:textwidth=72:

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.