Skip to content

Commit

Permalink
Merge branch 'develop' for 1.2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
AzothAmmo committed Aug 10, 2016
2 parents 42a45b6 + 1e5e648 commit bd839cc
Show file tree
Hide file tree
Showing 31 changed files with 406 additions and 174 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ if(NOT CMAKE_VERSION VERSION_LESS 3.0) # installing cereal requires INTERFACE li
option(JUST_INSTALL_CEREAL "Don't do anything besides installing the library" OFF)
endif()

option(THREAD_SAFE "Use mutexes to ensure thread safety" OFF)
if(THREAD_SAFE)
add_definitions(-DCEREAL_THREAD_SAFE=1)
set(CEREAL_THREAD_LIBS "pthread")
else()
set(CEREAL_THREAD_LIBS "")
endif()

if(NOT MSVC)
set(CMAKE_CXX_FLAGS "-Wall -Werror -g -Wextra -Wshadow -pedantic ${CMAKE_CXX_FLAGS}")
if(CMAKE_VERSION VERSION_LESS 3.1)
Expand Down
6 changes: 5 additions & 1 deletion include/cereal/archives/binary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ namespace cereal
itsStream(stream)
{ }

~BinaryOutputArchive() CEREAL_NOEXCEPT = default;

//! Writes size bytes of data to the output stream
void saveBinary( const void * data, std::size_t size )
{
Expand Down Expand Up @@ -90,7 +92,9 @@ namespace cereal
BinaryInputArchive(std::istream & stream) :
InputArchive<BinaryInputArchive, AllowEmptyClassElision>(this),
itsStream(stream)
{ }
{ }

~BinaryInputArchive() CEREAL_NOEXCEPT = default;

//! Reads size bytes of data from the input stream
void loadBinary( void * const data, std::size_t size )
Expand Down
10 changes: 8 additions & 2 deletions include/cereal/archives/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ namespace cereal
throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
#endif // RAPIDJSON_ASSERT

// Enable support for parsing of nan, inf, -inf
#define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag
#define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag

#include <cereal/external/rapidjson/prettywriter.h>
#include <cereal/external/rapidjson/ostreamwrapper.h>
#include <cereal/external/rapidjson/istreamwrapper.h>
Expand Down Expand Up @@ -155,7 +159,7 @@ namespace cereal
}

//! Destructor, flushes the JSON
~JSONOutputArchive()
~JSONOutputArchive() CEREAL_NOEXCEPT
{
if (itsNodeStack.top() == NodeType::InObject)
itsWriter.EndObject();
Expand Down Expand Up @@ -420,13 +424,15 @@ namespace cereal
itsNextName( nullptr ),
itsReadStream(stream)
{
itsDocument.ParseStream<rapidjson::kParseFullPrecisionFlag>(itsReadStream);
itsDocument.ParseStream<>(itsReadStream);
if (itsDocument.IsArray())
itsIteratorStack.emplace_back(itsDocument.Begin(), itsDocument.End());
else
itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
}

~JSONInputArchive() CEREAL_NOEXCEPT = default;

//! Loads some binary data, encoded as a base64 string
/*! This will automatically start and finish a node to load the data, and can be called directly by
users.
Expand Down
4 changes: 4 additions & 0 deletions include/cereal/archives/portable_binary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ namespace cereal
this->operator()( options.is_little_endian() );
}

~PortableBinaryOutputArchive() CEREAL_NOEXCEPT = default;

//! Writes size bytes of data to the output stream
template <std::size_t DataSize> inline
void saveBinary( const void * data, std::size_t size )
Expand Down Expand Up @@ -227,6 +229,8 @@ namespace cereal
itsConvertEndianness = options.is_little_endian() ^ streamLittleEndian;
}

~PortableBinaryInputArchive() CEREAL_NOEXCEPT = default;

//! Reads size bytes of data from the input stream
/*! @param data The data to save
@param size The number of bytes in the data
Expand Down
4 changes: 3 additions & 1 deletion include/cereal/archives/xml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ namespace cereal
}

//! Destructor, flushes the XML
~XMLOutputArchive()
~XMLOutputArchive() CEREAL_NOEXCEPT
{
const int flags = itsIndent ? 0x0 : rapidxml::print_no_indenting;
rapidxml::print( itsStream, itsXML, flags );
Expand Down Expand Up @@ -412,6 +412,8 @@ namespace cereal
itsNodes.emplace( root );
}

~XMLInputArchive() CEREAL_NOEXCEPT = default;

//! Loads some binary data, encoded as a base64 string, optionally specified by some name
/*! This will automatically start and finish a node to load the data, and can be called directly by
users.
Expand Down
1 change: 1 addition & 0 deletions include/cereal/cereal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ namespace cereal
{
static const auto hash = std::type_index(typeid(T)).hash_code();
const auto insertResult = itsVersionedTypes.insert( hash );
const auto lock = detail::StaticObject<detail::Versions>::lock();
const auto version =
detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );

Expand Down
24 changes: 0 additions & 24 deletions include/cereal/details/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,6 @@
#include <cereal/macros.hpp>
#include <cereal/details/static_object.hpp>

//! Defines the CEREAL_NOEXCEPT macro to use instead of noexcept
/*! If a compiler we support does not support noexcept, this macro
will detect this and define CEREAL_NOEXCEPT as a no-op */
#if !defined(CEREAL_HAS_NOEXCEPT)
#if defined(__clang__)
#if __has_feature(cxx_noexcept)
#define CEREAL_HAS_NOEXCEPT
#endif
#else // NOT clang
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
#define CEREAL_HAS_NOEXCEPT
#endif // end GCC/MSVC check
#endif // end NOT clang block

#ifndef CEREAL_NOEXCEPT
#ifdef CEREAL_HAS_NOEXCEPT
#define CEREAL_NOEXCEPT noexcept
#else
#define CEREAL_NOEXCEPT
#endif // end CEREAL_HAS_NOEXCEPT
#endif // end !defined(CEREAL_HAS_NOEXCEPT)
#endif // ifndef CEREAL_NOEXCEPT

namespace cereal
{
// ######################################################################
Expand Down
10 changes: 6 additions & 4 deletions include/cereal/details/polymorphic_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ namespace cereal
static bool exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
{
// First phase of lookup - match base type index
auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseIter = baseMap.find( baseIndex );
if (baseIter == baseMap.end())
return false;
Expand All @@ -151,7 +151,7 @@ namespace cereal
static std::vector<PolymorphicCaster const *> const & lookup( std::type_index const & baseIndex, std::type_index const & derivedIndex, F && exceptionFunc )
{
// First phase of lookup - match base type index
auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseIter = baseMap.find( baseIndex );
if( baseIter == baseMap.end() )
exceptionFunc();
Expand All @@ -161,7 +161,7 @@ namespace cereal
auto derivedIter = derivedMap.find( derivedIndex );
if( derivedIter == derivedMap.end() )
exceptionFunc();

return derivedIter->second;
}

Expand Down Expand Up @@ -218,6 +218,7 @@ namespace cereal
assuming dynamic type information is available */
PolymorphicVirtualCaster()
{
const auto lock = StaticObject<PolymorphicCasters>::lock();
auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseKey = std::type_index(typeid(Base));
auto lb = baseMap.lower_bound(baseKey);
Expand All @@ -236,7 +237,7 @@ namespace cereal
auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo)
{
const bool exists = PolymorphicCasters::exists( baseInfo, derivedInfo );
return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) :
return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) :
std::vector<PolymorphicCaster const *>{} );
};

Expand Down Expand Up @@ -409,6 +410,7 @@ namespace cereal
InputBindingCreator()
{
auto & map = StaticObject<InputBindingMap<Archive>>::getInstance().map;
auto lock = StaticObject<InputBindingMap<Archive>>::lock();
auto key = std::string(binding_name<T>::name());
auto lb = map.lower_bound(key);

Expand Down
44 changes: 43 additions & 1 deletion include/cereal/details/static_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_

#include <cereal/macros.hpp>

#if CEREAL_THREAD_SAFE
#include <mutex>
#endif

//! Prevent link optimization from removing non-referenced static objects
/*! Especially for polymorphic support, we create static objects which
may not ever be explicitly referenced. Most linkers will detect this
Expand Down Expand Up @@ -79,12 +85,48 @@ namespace cereal
return create();
}

//! A class that acts like std::lock_guard
class LockGuard
{
#if CEREAL_THREAD_SAFE
public:
LockGuard(std::mutex & m) : lock(m) {}
private:
std::unique_lock<std::mutex> lock;
#else
public:
~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
#endif
};

//! Attempts to lock this static object for the current scope
/*! @note This function is a no-op if cereal is not compiled with
thread safety enabled (CEREAL_THREAD_SAFE = 1).
This function returns an object that holds a lock for
this StaticObject that will release its lock upon destruction. This
call will block until the lock is available. */
static LockGuard lock()
{
#if CEREAL_THREAD_SAFE
return LockGuard{instanceMutex};
#else
return LockGuard{};
#endif
}

private:
static T & instance;
#if CEREAL_THREAD_SAFE
static std::mutex instanceMutex;
#endif
};

template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
#if CEREAL_THREAD_SAFE
template <class T> std::mutex StaticObject<T>::instanceMutex;
#endif
} // namespace detail
} // namespace cereal

#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
32 changes: 20 additions & 12 deletions include/cereal/external/rapidjson/allocators.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ class MemoryPoolAllocator {

size = CEREAL_RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL;

void *buffer = reinterpret_cast<char *>(chunkHead_) + CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
Expand Down Expand Up @@ -211,11 +212,13 @@ class MemoryPoolAllocator {
}

// Realloc process: allocate and copy memory, do not free original buffer.
void* newBuffer = Malloc(newSize);
CEREAL_RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize);
return newBuffer;
if (void* newBuffer = Malloc(newSize)) {
if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize);
return newBuffer;
}
else
return NULL;
}

//! Frees a memory block (concept Allocator)
Expand All @@ -229,15 +232,20 @@ class MemoryPoolAllocator {

//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
void AddChunk(size_t capacity) {
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = CEREAL_RAPIDJSON_NEW(BaseAllocator());
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
return true;
}
else
return false;
}

static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
Expand Down
Loading

0 comments on commit bd839cc

Please sign in to comment.