mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-23 08:31:45 +02:00
Removed redundant try-catch, zone's constructor never throw.
In the C++11 version, added noexcept. In the C++03 version, added throw() as comments because actual throw() introduces some overhead. Untabified.
This commit is contained in:
@@ -149,7 +149,7 @@ private:
|
|||||||
finalizer_array finalizer_array_;
|
finalizer_array finalizer_array_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
|
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static zone* create(size_t chunk_size);
|
static zone* create(size_t chunk_size);
|
||||||
@@ -185,13 +185,7 @@ inline zone* zone::create(size_t chunk_size)
|
|||||||
if (!z) {
|
if (!z) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
try {
|
new (z) zone(chunk_size);
|
||||||
new (z) zone(chunk_size);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
::free(z);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +195,7 @@ inline void zone::destroy(zone* z)
|
|||||||
::free(z);
|
::free(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline zone::zone(size_t chunk_size):chunk_size_(chunk_size), chunk_list_(chunk_size_)
|
inline zone::zone(size_t chunk_size) noexcept:chunk_size_(chunk_size), chunk_list_(chunk_size_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,17 +3,17 @@
|
|||||||
//
|
//
|
||||||
// Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
// Copyright (C) 2008-2010 FURUHASHI Sadayuki
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
#ifndef MSGPACK_ZONE_HPP
|
#ifndef MSGPACK_ZONE_HPP
|
||||||
#define MSGPACK_ZONE_HPP
|
#define MSGPACK_ZONE_HPP
|
||||||
@@ -36,275 +36,268 @@
|
|||||||
namespace msgpack {
|
namespace msgpack {
|
||||||
|
|
||||||
class zone {
|
class zone {
|
||||||
struct finalizer {
|
struct finalizer {
|
||||||
finalizer(void (*func)(void*), void* data):func_(func), data_(data) {}
|
finalizer(void (*func)(void*), void* data):func_(func), data_(data) {}
|
||||||
void operator()() { func_(data_); }
|
void operator()() { func_(data_); }
|
||||||
void (*func_)(void*);
|
void (*func_)(void*);
|
||||||
void* data_;
|
void* data_;
|
||||||
};
|
};
|
||||||
struct finalizer_array {
|
struct finalizer_array {
|
||||||
finalizer_array():tail_(nullptr), end_(nullptr), array_(nullptr) {}
|
finalizer_array():tail_(nullptr), end_(nullptr), array_(nullptr) {}
|
||||||
void call() {
|
void call() {
|
||||||
finalizer* fin = tail_;
|
finalizer* fin = tail_;
|
||||||
for(; fin != array_; --fin) (*(fin-1))();
|
for(; fin != array_; --fin) (*(fin-1))();
|
||||||
}
|
}
|
||||||
~finalizer_array() {
|
~finalizer_array() {
|
||||||
call();
|
call();
|
||||||
::free(array_);
|
::free(array_);
|
||||||
}
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
call();
|
call();
|
||||||
tail_ = array_;
|
tail_ = array_;
|
||||||
}
|
}
|
||||||
void push(void (*func)(void* data), void* data)
|
void push(void (*func)(void* data), void* data)
|
||||||
{
|
{
|
||||||
finalizer* fin = tail_;
|
finalizer* fin = tail_;
|
||||||
|
|
||||||
if(fin == end_) {
|
|
||||||
push_expand(func, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fin->func_ = func;
|
|
||||||
fin->data_ = data;
|
|
||||||
|
|
||||||
++tail_;
|
|
||||||
}
|
|
||||||
void push_expand(void (*func)(void*), void* data) {
|
|
||||||
const size_t nused = end_ - array_;
|
|
||||||
size_t nnext;
|
|
||||||
if(nused == 0) {
|
|
||||||
nnext = (sizeof(finalizer) < 72/2) ?
|
|
||||||
72 / sizeof(finalizer) : 8;
|
|
||||||
} else {
|
|
||||||
nnext = nused * 2;
|
|
||||||
}
|
|
||||||
finalizer* tmp =
|
|
||||||
static_cast<finalizer*>(::realloc(array_, sizeof(finalizer) * nnext));
|
|
||||||
if(!tmp) {
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
array_ = tmp;
|
|
||||||
end_ = tmp + nnext;
|
|
||||||
tail_ = tmp + nused;
|
|
||||||
new (tail_) finalizer(func, data);
|
|
||||||
|
|
||||||
++tail_;
|
if(fin == end_) {
|
||||||
}
|
push_expand(func, data);
|
||||||
finalizer* tail_;
|
return;
|
||||||
finalizer* end_;
|
}
|
||||||
finalizer* array_;
|
|
||||||
};
|
fin->func_ = func;
|
||||||
struct chunk {
|
fin->data_ = data;
|
||||||
chunk* next_;
|
|
||||||
};
|
++tail_;
|
||||||
struct chunk_list {
|
}
|
||||||
chunk_list(size_t chunk_size)
|
void push_expand(void (*func)(void*), void* data) {
|
||||||
{
|
const size_t nused = end_ - array_;
|
||||||
chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + chunk_size));
|
size_t nnext;
|
||||||
if(!c) {
|
if(nused == 0) {
|
||||||
throw std::bad_alloc();
|
nnext = (sizeof(finalizer) < 72/2) ?
|
||||||
}
|
72 / sizeof(finalizer) : 8;
|
||||||
|
} else {
|
||||||
head_ = c;
|
nnext = nused * 2;
|
||||||
free_ = chunk_size;
|
}
|
||||||
ptr_ = reinterpret_cast<char*>(c) + sizeof(chunk);
|
finalizer* tmp =
|
||||||
c->next_ = nullptr;
|
static_cast<finalizer*>(::realloc(array_, sizeof(finalizer) * nnext));
|
||||||
}
|
if(!tmp) {
|
||||||
~chunk_list()
|
throw std::bad_alloc();
|
||||||
{
|
}
|
||||||
chunk* c = head_;
|
array_ = tmp;
|
||||||
while(true) {
|
end_ = tmp + nnext;
|
||||||
chunk* n = c->next_;
|
tail_ = tmp + nused;
|
||||||
::free(c);
|
new (tail_) finalizer(func, data);
|
||||||
if(n) {
|
|
||||||
c = n;
|
++tail_;
|
||||||
} else {
|
}
|
||||||
break;
|
finalizer* tail_;
|
||||||
}
|
finalizer* end_;
|
||||||
}
|
finalizer* array_;
|
||||||
}
|
};
|
||||||
void clear(size_t chunk_size)
|
struct chunk {
|
||||||
{
|
chunk* next_;
|
||||||
chunk* c = head_;
|
};
|
||||||
while(true) {
|
struct chunk_list {
|
||||||
chunk* n = c->next_;
|
chunk_list(size_t chunk_size)
|
||||||
if(n) {
|
{
|
||||||
::free(c);
|
chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + chunk_size));
|
||||||
c = n;
|
if(!c) {
|
||||||
} else {
|
throw std::bad_alloc();
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
head_ = c;
|
||||||
head_->next_ = nullptr;
|
free_ = chunk_size;
|
||||||
free_ = chunk_size;
|
ptr_ = reinterpret_cast<char*>(c) + sizeof(chunk);
|
||||||
ptr_ = reinterpret_cast<char*>(head_) + sizeof(chunk);
|
c->next_ = nullptr;
|
||||||
}
|
}
|
||||||
size_t free_;
|
~chunk_list()
|
||||||
char* ptr_;
|
{
|
||||||
chunk* head_;
|
chunk* c = head_;
|
||||||
};
|
while(true) {
|
||||||
size_t chunk_size_;
|
chunk* n = c->next_;
|
||||||
chunk_list chunk_list_;
|
::free(c);
|
||||||
finalizer_array finalizer_array_;
|
if(n) {
|
||||||
|
c = n;
|
||||||
public:
|
} else {
|
||||||
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void clear(size_t chunk_size)
|
||||||
|
{
|
||||||
|
chunk* c = head_;
|
||||||
|
while(true) {
|
||||||
|
chunk* n = c->next_;
|
||||||
|
if(n) {
|
||||||
|
::free(c);
|
||||||
|
c = n;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
head_->next_ = nullptr;
|
||||||
|
free_ = chunk_size;
|
||||||
|
ptr_ = reinterpret_cast<char*>(head_) + sizeof(chunk);
|
||||||
|
}
|
||||||
|
size_t free_;
|
||||||
|
char* ptr_;
|
||||||
|
chunk* head_;
|
||||||
|
};
|
||||||
|
size_t chunk_size_;
|
||||||
|
chunk_list chunk_list_;
|
||||||
|
finalizer_array finalizer_array_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static zone* create(size_t chunk_size);
|
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE) /* throw() */;
|
||||||
static void destroy(zone* zone);
|
|
||||||
void* malloc(size_t size);
|
|
||||||
void* malloc_no_align(size_t size);
|
|
||||||
|
|
||||||
void push_finalizer(void (*func)(void*), void* data);
|
public:
|
||||||
|
static zone* create(size_t chunk_size);
|
||||||
|
static void destroy(zone* zone);
|
||||||
|
void* malloc(size_t size);
|
||||||
|
void* malloc_no_align(size_t size);
|
||||||
|
|
||||||
template <typename T>
|
void push_finalizer(void (*func)(void*), void* data);
|
||||||
void push_finalizer(msgpack::unique_ptr<T> obj);
|
|
||||||
|
|
||||||
void clear();
|
template <typename T>
|
||||||
|
void push_finalizer(msgpack::unique_ptr<T> obj);
|
||||||
|
|
||||||
void swap(zone& o);
|
void clear();
|
||||||
|
|
||||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
void swap(zone& o);
|
||||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
|
||||||
T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
|
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||||
<%}%>
|
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||||
|
T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
|
||||||
|
<%}%>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void undo_malloc(size_t size);
|
void undo_malloc(size_t size);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void object_destructor(void* obj);
|
static void object_destructor(void* obj);
|
||||||
|
|
||||||
void* malloc_expand(size_t size);
|
void* malloc_expand(size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline zone* zone::create(size_t chunk_size)
|
inline zone* zone::create(size_t chunk_size)
|
||||||
{
|
{
|
||||||
zone* z = static_cast<zone*>(::malloc(sizeof(zone) + chunk_size));
|
zone* z = static_cast<zone*>(::malloc(sizeof(zone) + chunk_size));
|
||||||
if (!z) {
|
if (!z) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
try {
|
new (z) zone(chunk_size);
|
||||||
new (z) zone(chunk_size);
|
return z;
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
::free(z);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void zone::destroy(zone* z)
|
inline void zone::destroy(zone* z)
|
||||||
{
|
{
|
||||||
z->~zone();
|
z->~zone();
|
||||||
::free(z);
|
::free(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline zone::zone(size_t chunk_size):chunk_size_(chunk_size), chunk_list_(chunk_size_)
|
inline zone::zone(size_t chunk_size) /* throw() */ :chunk_size_(chunk_size), chunk_list_(chunk_size_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* zone::malloc(size_t size)
|
inline void* zone::malloc(size_t size)
|
||||||
{
|
{
|
||||||
return malloc_no_align(
|
return malloc_no_align(
|
||||||
((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1));
|
((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* zone::malloc_no_align(size_t size)
|
inline void* zone::malloc_no_align(size_t size)
|
||||||
{
|
{
|
||||||
if(chunk_list_.free_ < size) {
|
if(chunk_list_.free_ < size) {
|
||||||
return malloc_expand(size);
|
return malloc_expand(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ptr = chunk_list_.ptr_;
|
char* ptr = chunk_list_.ptr_;
|
||||||
chunk_list_.free_ -= size;
|
chunk_list_.free_ -= size;
|
||||||
chunk_list_.ptr_ += size;
|
chunk_list_.ptr_ += size;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* zone::malloc_expand(size_t size)
|
inline void* zone::malloc_expand(size_t size)
|
||||||
{
|
{
|
||||||
chunk_list* const cl = &chunk_list_;
|
chunk_list* const cl = &chunk_list_;
|
||||||
|
|
||||||
size_t sz = chunk_size_;
|
size_t sz = chunk_size_;
|
||||||
|
|
||||||
while(sz < size) {
|
while(sz < size) {
|
||||||
sz *= 2;
|
sz *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + sz));
|
chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + sz));
|
||||||
|
|
||||||
char* ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
|
char* ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
|
||||||
|
|
||||||
c->next_ = cl->head_;
|
c->next_ = cl->head_;
|
||||||
cl->head_ = c;
|
cl->head_ = c;
|
||||||
cl->free_ = sz - size;
|
cl->free_ = sz - size;
|
||||||
cl->ptr_ = ptr + size;
|
cl->ptr_ = ptr + size;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void zone::push_finalizer(void (*func)(void*), void* data)
|
inline void zone::push_finalizer(void (*func)(void*), void* data)
|
||||||
{
|
{
|
||||||
finalizer_array_.push(func, data);
|
finalizer_array_.push(func, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
|
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
|
||||||
{
|
{
|
||||||
finalizer_array_.push(&zone::object_destructor<T>, obj.get());
|
finalizer_array_.push(&zone::object_destructor<T>, obj.get());
|
||||||
obj.release();
|
obj.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void zone::clear()
|
inline void zone::clear()
|
||||||
{
|
{
|
||||||
finalizer_array_.clear();
|
finalizer_array_.clear();
|
||||||
chunk_list_.clear(chunk_size_);
|
chunk_list_.clear(chunk_size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void zone::swap(zone& o)
|
inline void zone::swap(zone& o)
|
||||||
{
|
{
|
||||||
std::swap(*this, o);
|
std::swap(*this, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void zone::object_destructor(void* obj)
|
void zone::object_destructor(void* obj)
|
||||||
{
|
{
|
||||||
reinterpret_cast<T*>(obj)->~T();
|
reinterpret_cast<T*>(obj)->~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void zone::undo_malloc(size_t size)
|
inline void zone::undo_malloc(size_t size)
|
||||||
{
|
{
|
||||||
chunk_list_.ptr_ -= size;
|
chunk_list_.ptr_ -= size;
|
||||||
chunk_list_.free_ += size;
|
chunk_list_.free_ += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||||
T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||||
{
|
{
|
||||||
void* x = malloc(sizeof(T));
|
void* x = malloc(sizeof(T));
|
||||||
try {
|
try {
|
||||||
finalizer_array_.push(&zone::object_destructor<T>, x);
|
finalizer_array_.push(&zone::object_destructor<T>, x);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
undo_malloc(sizeof(T));
|
undo_malloc(sizeof(T));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
|
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
--finalizer_array_.tail_;
|
--finalizer_array_.tail_;
|
||||||
undo_malloc(sizeof(T));
|
undo_malloc(sizeof(T));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
|
|
||||||
} // namespace msgpack
|
} // namespace msgpack
|
||||||
|
|
||||||
#endif /* msgpack/zone.hpp */
|
#endif /* msgpack/zone.hpp */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user