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:
Takatoshi Kondo
2013-09-04 14:47:38 +09:00
parent 7593e5ce0e
commit 72b3064a67
2 changed files with 195 additions and 208 deletions

View File

@@ -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_)
{ {
} }

View File

@@ -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 */