diff --git a/src/internal_modules/roc_address/protocol_map.cpp b/src/internal_modules/roc_address/protocol_map.cpp index 674bc8b17..7d7787b02 100644 --- a/src/internal_modules/roc_address/protocol_map.cpp +++ b/src/internal_modules/roc_address/protocol_map.cpp @@ -133,10 +133,9 @@ bool ProtocolMap::get_supported_interfaces(core::Array& interface_arr } if (n_iface == (unsigned)protos_[n_proto].iface) { - if (!interface_array.grow(interface_array.size() + 1)) { + if (!interface_array.push_back(protos_[n_proto].iface)) { return false; } - interface_array.push_back(protos_[n_proto].iface); interfaces_exist = true; break; } diff --git a/src/internal_modules/roc_core/array.h b/src/internal_modules/roc_core/array.h index 22ab06645..8f81b3464 100644 --- a/src/internal_modules/roc_core/array.h +++ b/src/internal_modules/roc_core/array.h @@ -123,15 +123,17 @@ template class Array : public NonCopyable } //! Append element to array. - //! @pre - //! Array size() should be less than max_size(). - void push_back(const T& value) { - if (size_ >= max_size_) { - roc_panic("array: attempting to append element to full array: size=%lu", - (unsigned long)size_); + //! @returns + //! false if the allocation failed + ROC_ATTR_NODISCARD bool push_back(const T& value) { + if (!grow_exp(size() + 1)) { + return false; } + new (data_ + size_) T(value); size_++; + + return true; } //! Set array size. diff --git a/src/internal_modules/roc_core/hashmap.h b/src/internal_modules/roc_core/hashmap.h index a7eb0a1c6..4d5ce7f7c 100644 --- a/src/internal_modules/roc_core/hashmap.h +++ b/src/internal_modules/roc_core/hashmap.h @@ -154,7 +154,7 @@ class Hashmap : public NonCopyable<> { const hashsum_t hash = T::key_hash(key); HashmapNode::HashmapNodeData* node = impl_.find_node( hash, (const void*)&key, - &Hashmap::key_equal); + &Hashmap::key_equal_); if (!node) { return NULL; } @@ -208,8 +208,10 @@ class Hashmap : public NonCopyable<> { //! @remarks //! - acquires ownership of @p element //! + //! @returns + //! false if the allocation failed + //! //! @pre - //! - hashmap size() should be smaller than hashmap capacity() //! - @p element should not be member of any hashmap //! - hashmap shouldn't have an element with the same key //! @@ -223,10 +225,13 @@ class Hashmap : public NonCopyable<> { //! Insertion speed is higher when insert to remove ratio is close to one or lower, //! and slows down when it becomes higher than one. The slow down is caused by //! the incremental rehashing algorithm. - void insert(T& element) { + ROC_ATTR_NODISCARD bool insert(T& element) { HashmapNode::HashmapNodeData* node = element.hashmap_node_data(); - insert_(element.key(), node); + if (!insert_(element.key(), node)) { + return false; + } OwnershipPolicy::acquire(element); + return true; } //! Remove element from hashmap. @@ -284,17 +289,18 @@ class Hashmap : public NonCopyable<> { } template - static bool key_equal(HashmapNode::HashmapNodeData* node, const void* key) { + static bool key_equal_(HashmapNode::HashmapNodeData* node, const void* key) { T* elem = container_of_(node); const Key& key_ref = *(const Key*)key; return T::key_equal(elem->key(), key_ref); } template - void insert_(const Key& key, HashmapNode::HashmapNodeData* node) { + bool insert_(const Key& key, HashmapNode::HashmapNodeData* node) { const hashsum_t hash = T::key_hash(key); - impl_.insert(node, hash, (const void*)&key, - &Hashmap::key_equal); + return impl_.insert( + node, hash, (const void*)&key, + &Hashmap::key_equal_); } AlignedStorage embedded_buckets_; diff --git a/src/internal_modules/roc_core/hashmap_impl.cpp b/src/internal_modules/roc_core/hashmap_impl.cpp index b33122e60..306f1a523 100644 --- a/src/internal_modules/roc_core/hashmap_impl.cpp +++ b/src/internal_modules/roc_core/hashmap_impl.cpp @@ -105,12 +105,14 @@ HashmapImpl::nextof(HashmapNode::HashmapNodeData* node) const { return node->all_next; } -void HashmapImpl::insert(HashmapNode::HashmapNodeData* node, +bool HashmapImpl::insert(HashmapNode::HashmapNodeData* node, hashsum_t hash, const void* key, key_equals_callback key_equals) { if (size_ >= buckets_capacity_(n_curr_buckets_)) { - roc_panic("hashmap: attempt to insert into full hashmap before calling grow()"); + if (!grow()) { + return false; + } } if (node->bucket != NULL) { @@ -131,6 +133,8 @@ void HashmapImpl::insert(HashmapNode::HashmapNodeData* node, size_++; proceed_rehash_(true); + + return true; } void HashmapImpl::remove(HashmapNode::HashmapNodeData* node, bool skip_rehash) { diff --git a/src/internal_modules/roc_core/hashmap_impl.h b/src/internal_modules/roc_core/hashmap_impl.h index 38f70f8da..eb584423e 100644 --- a/src/internal_modules/roc_core/hashmap_impl.h +++ b/src/internal_modules/roc_core/hashmap_impl.h @@ -75,7 +75,7 @@ class HashmapImpl { HashmapNode::HashmapNodeData* nextof(HashmapNode::HashmapNodeData* node) const; //! Insert node into hashmap. - void insert(HashmapNode::HashmapNodeData* node, + bool insert(HashmapNode::HashmapNodeData* node, hashsum_t hash, const void* key, key_equals_callback callback); diff --git a/src/internal_modules/roc_node/receiver.cpp b/src/internal_modules/roc_node/receiver.cpp index 3f1e8dc93..2b5800941 100644 --- a/src/internal_modules/roc_node/receiver.cpp +++ b/src/internal_modules/roc_node/receiver.cpp @@ -341,13 +341,12 @@ core::SharedPtr Receiver::get_slot_(slot_index_t slot_index, return NULL; } - if (!slot_map_.grow()) { + if (!slot_map_.insert(*slot)) { roc_log(LogError, "receiver node: failed to create slot %lu", (unsigned long)slot_index); return NULL; } - slot_map_.insert(*slot); } else { roc_log(LogError, "receiver node: failed to find slot %lu", (unsigned long)slot_index); diff --git a/src/internal_modules/roc_node/sender.cpp b/src/internal_modules/roc_node/sender.cpp index 89e8b2e00..5436f8649 100644 --- a/src/internal_modules/roc_node/sender.cpp +++ b/src/internal_modules/roc_node/sender.cpp @@ -338,13 +338,11 @@ core::SharedPtr Sender::get_slot_(slot_index_t slot_index, return NULL; } - if (!slot_map_.grow()) { + if (!slot_map_.insert(*slot)) { roc_log(LogError, "sender node: failed to create slot %lu", (unsigned long)slot_index); return NULL; } - - slot_map_.insert(*slot); } else { roc_log(LogError, "sender node: failed to find slot %lu", (unsigned long)slot_index); diff --git a/src/internal_modules/roc_packet/router.cpp b/src/internal_modules/roc_packet/router.cpp index d968afe69..c1e6704a2 100644 --- a/src/internal_modules/roc_packet/router.cpp +++ b/src/internal_modules/roc_packet/router.cpp @@ -19,18 +19,17 @@ Router::Router(core::IArena& arena) } bool Router::add_route(IWriter& writer, unsigned flags) { - if (!routes_.grow_exp(routes_.size() + 1)) { - roc_log(LogError, "router: can't allocate route"); - return false; - } - Route r; r.writer = &writer; r.flags = flags; r.source = 0; r.has_source = false; - routes_.push_back(r); + if (!routes_.push_back(r)) { + roc_log(LogError, "router: can't allocate route"); + return false; + } + return true; } diff --git a/src/internal_modules/roc_rtp/format_map.cpp b/src/internal_modules/roc_rtp/format_map.cpp index a77afedd4..6ddaf6e26 100644 --- a/src/internal_modules/roc_rtp/format_map.cpp +++ b/src/internal_modules/roc_rtp/format_map.cpp @@ -85,12 +85,6 @@ bool FormatMap::add_format(const Format& fmt) { roc_panic("format map: bad format: invalid codec functions"); } - if (!node_map_.grow()) { - roc_log(LogError, - "format map: failed to register format: hashmap allocation failed"); - return false; - } - if (node_map_.find(fmt.payload_type)) { roc_log(LogError, "format map: failed to register format: payload type %u already exists", @@ -106,7 +100,11 @@ bool FormatMap::add_format(const Format& fmt) { return false; } - node_map_.insert(*node); + if (!node_map_.insert(*node)) { + roc_log(LogError, + "format map: failed to register format: hashmap allocation failed"); + return false; + } return true; } diff --git a/src/internal_modules/roc_sdp/media_description.cpp b/src/internal_modules/roc_sdp/media_description.cpp index d783c5c0c..8f4051b71 100644 --- a/src/internal_modules/roc_sdp/media_description.cpp +++ b/src/internal_modules/roc_sdp/media_description.cpp @@ -97,11 +97,10 @@ bool MediaDescription::set_nb_ports(long nb_ports) { } bool MediaDescription::add_payload_id(unsigned payload_id) { - if (!payload_ids_.grow_exp(payload_ids_.size() + 1)) { + if (!payload_ids_.push_back(payload_id)) { return false; } - payload_ids_.push_back(payload_id); return true; } @@ -114,11 +113,10 @@ bool MediaDescription::add_connection_data(address::AddrFamily addrtype, return false; } - if (!connection_data_.grow_exp(connection_data_.size() + 1)) { + if (!connection_data_.push_back(c)) { return false; } - connection_data_.push_back(c); return true; } diff --git a/src/internal_modules/roc_sndio/backend_map.cpp b/src/internal_modules/roc_sndio/backend_map.cpp index f5a50ce7f..5b85550e3 100644 --- a/src/internal_modules/roc_sndio/backend_map.cpp +++ b/src/internal_modules/roc_sndio/backend_map.cpp @@ -46,17 +46,13 @@ void BackendMap::set_frame_size(core::nanoseconds_t frame_length, } void BackendMap::register_backends_() { - if (!backends_.grow(MaxBackends)) { - roc_panic("backend map: can't grow backends array"); - } - #ifdef ROC_TARGET_PULSEAUDIO pulseaudio_backend_.reset(new (pulseaudio_backend_) PulseaudioBackend); - backends_.push_back(pulseaudio_backend_.get()); + add_backend_(pulseaudio_backend_.get()); #endif // ROC_TARGET_PULSEAUDIO #ifdef ROC_TARGET_SOX sox_backend_.reset(new (sox_backend_) SoxBackend); - backends_.push_back(sox_backend_.get()); + add_backend_(sox_backend_.get()); #endif // ROC_TARGET_SOX } @@ -66,5 +62,11 @@ void BackendMap::register_drivers_() { } } +void BackendMap::add_backend_(IBackend* backend) { + if (!backends_.push_back(backend)) { + roc_panic("backend map: can't register backend"); + } +} + } // namespace sndio } // namespace roc diff --git a/src/internal_modules/roc_sndio/backend_map.h b/src/internal_modules/roc_sndio/backend_map.h index 058e50587..019cf6ccd 100644 --- a/src/internal_modules/roc_sndio/backend_map.h +++ b/src/internal_modules/roc_sndio/backend_map.h @@ -61,6 +61,8 @@ class BackendMap : public core::NonCopyable<> { void register_backends_(); void register_drivers_(); + void add_backend_(IBackend*); + #ifdef ROC_TARGET_PULSEAUDIO core::Optional pulseaudio_backend_; #endif // ROC_TARGET_PULSEAUDIO diff --git a/src/internal_modules/roc_sndio/target_pulseaudio/roc_sndio/pulseaudio_backend.cpp b/src/internal_modules/roc_sndio/target_pulseaudio/roc_sndio/pulseaudio_backend.cpp index 86ab16e41..733e6315b 100644 --- a/src/internal_modules/roc_sndio/target_pulseaudio/roc_sndio/pulseaudio_backend.cpp +++ b/src/internal_modules/roc_sndio/target_pulseaudio/roc_sndio/pulseaudio_backend.cpp @@ -23,14 +23,12 @@ PulseaudioBackend::PulseaudioBackend() { void PulseaudioBackend::discover_drivers( core::Array& driver_list) { - if (!driver_list.grow(driver_list.size() + 1)) { - roc_panic("pulseaudio backend: can't grow drivers array"); + if (!driver_list.push_back(DriverInfo("pulse", DriverType_Device, + DriverFlag_IsDefault | DriverFlag_SupportsSink + | DriverFlag_SupportsSource, + this))) { + roc_panic("pulseaudio backend: can't add driver"); } - - driver_list.push_back(DriverInfo("pulse", DriverType_Device, - DriverFlag_IsDefault | DriverFlag_SupportsSink - | DriverFlag_SupportsSource, - this)); } IDevice* PulseaudioBackend::open_device(DeviceType device_type, diff --git a/src/internal_modules/roc_sndio/target_sox/roc_sndio/sox_backend.cpp b/src/internal_modules/roc_sndio/target_sox/roc_sndio/sox_backend.cpp index 67a69ba5f..b3a4aff16 100644 --- a/src/internal_modules/roc_sndio/target_sox/roc_sndio/sox_backend.cpp +++ b/src/internal_modules/roc_sndio/target_sox/roc_sndio/sox_backend.cpp @@ -192,14 +192,13 @@ void SoxBackend::discover_drivers(core::Array& driver_li const char* driver = map_from_sox_driver(default_drivers[n]); - if (!driver_list.grow(driver_list.size() + 1)) { - roc_panic("sox backend: can't grow drivers array"); + if (!driver_list.push_back(DriverInfo(driver, DriverType_Device, + DriverFlag_IsDefault + | DriverFlag_SupportsSource + | DriverFlag_SupportsSink, + this))) { + roc_panic("sox backend: can't add driver"); } - - driver_list.push_back(DriverInfo(driver, DriverType_Device, - DriverFlag_IsDefault | DriverFlag_SupportsSource - | DriverFlag_SupportsSink, - this)); } const sox_format_tab_t* formats = sox_get_format_fns(); @@ -215,14 +214,13 @@ void SoxBackend::discover_drivers(core::Array& driver_li continue; } - if (!driver_list.grow(driver_list.size() + 1)) { - roc_panic("sox backend: can't grow drivers array"); + if (!driver_list.push_back(DriverInfo( + driver, + (handler->flags & SOX_FILE_DEVICE) ? DriverType_Device + : DriverType_File, + DriverFlag_SupportsSource | DriverFlag_SupportsSink, this))) { + roc_panic("sox backend: can't add driver"); } - - driver_list.push_back(DriverInfo( - driver, - (handler->flags & SOX_FILE_DEVICE) ? DriverType_Device : DriverType_File, - DriverFlag_SupportsSource | DriverFlag_SupportsSink, this)); } } } diff --git a/src/tests/roc_core/test_array.cpp b/src/tests/roc_core/test_array.cpp index ebd413cfe..9fbab2383 100644 --- a/src/tests/roc_core/test_array.cpp +++ b/src/tests/roc_core/test_array.cpp @@ -120,7 +120,7 @@ TEST(array, push_back) { CHECK(array.grow(NumObjects)); for (size_t n = 0; n < NumObjects; n++) { - array.push_back(Object(n)); + CHECK(array.push_back(Object(n))); LONGS_EQUAL(NumObjects, array.capacity()); LONGS_EQUAL(n + 1, array.size()); @@ -174,9 +174,9 @@ TEST(array, constructor_destructor) { CHECK(array.grow(3)); - array.push_back(Object(1)); - array.push_back(Object(2)); - array.push_back(Object(3)); + CHECK(array.push_back(Object(1))); + CHECK(array.push_back(Object(2))); + CHECK(array.push_back(Object(3))); LONGS_EQUAL(0, arena.num_allocations()); LONGS_EQUAL(3, Object::n_objects); @@ -186,8 +186,8 @@ TEST(array, constructor_destructor) { LONGS_EQUAL(1, arena.num_allocations()); LONGS_EQUAL(3, Object::n_objects); - array.push_back(Object(4)); - array.push_back(Object(5)); + CHECK(array.push_back(Object(4))); + CHECK(array.push_back(Object(5))); LONGS_EQUAL(1, arena.num_allocations()); LONGS_EQUAL(5, Object::n_objects); diff --git a/src/tests/roc_core/test_hashmap.cpp b/src/tests/roc_core/test_hashmap.cpp index d3988044c..b566af767 100644 --- a/src/tests/roc_core/test_hashmap.cpp +++ b/src/tests/roc_core/test_hashmap.cpp @@ -87,7 +87,7 @@ TEST_GROUP(hashmap) { format_key(key, sizeof(key), n); SharedPtr obj = new Object(key); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); } CHECK((ssize_t)n >= (ssize_t)Capacity); @@ -113,7 +113,7 @@ TEST(hashmap, insert) { CHECK(hashmap.grow()); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); UNSIGNED_LONGS_EQUAL(1, hashmap.size()); CHECK(hashmap.find("foo") == obj); @@ -129,7 +129,7 @@ TEST(hashmap, remove) { CHECK(hashmap.grow()); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); UNSIGNED_LONGS_EQUAL(1, hashmap.size()); CHECK(hashmap.find("foo")); @@ -159,7 +159,7 @@ TEST(hashmap, insert_remove_many) { CHECK(hashmap.size() < hashmap.capacity()); } - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); } UNSIGNED_LONGS_EQUAL(NumElements, hashmap.size()); @@ -212,7 +212,7 @@ TEST(hashmap, grow_rapidly) { format_key(key, sizeof(key), n_elems++); SharedPtr obj = new Object(key); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); UNSIGNED_LONGS_EQUAL(n_elems, hashmap.size()); } @@ -238,7 +238,7 @@ TEST(hashmap, grow_rapidly_embedding) { format_key(key, sizeof(key), n_elems++); SharedPtr obj = new Object(key); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); } UNSIGNED_LONGS_EQUAL(n_elems, hashmap.size()); @@ -280,7 +280,7 @@ TEST(hashmap, grow_slowly) { CHECK(hashmap.size() < hashmap.capacity()); } - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); } if (n > StartSize && n % GrowthRatio != 0) { @@ -309,8 +309,8 @@ TEST(hashmap, refcounting) { CHECK(hashmap.grow()); - hashmap.insert(*obj1); - hashmap.insert(*obj2); + CHECK(hashmap.insert(*obj1)); + CHECK(hashmap.insert(*obj2)); UNSIGNED_LONGS_EQUAL(2, obj1->getref()); UNSIGNED_LONGS_EQUAL(2, obj2->getref()); @@ -352,7 +352,7 @@ TEST(hashmap, iterate) { SharedPtr obj = new Object(key); CHECK(hashmap.grow()); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); objects[n] = obj; @@ -387,7 +387,7 @@ TEST(hashmap, iterate_modify) { SharedPtr obj = new Object(key); CHECK(hashmap.grow()); - hashmap.insert(*obj); + CHECK(hashmap.insert(*obj)); objects[n] = obj; @@ -411,7 +411,7 @@ TEST(hashmap, iterate_modify) { SharedPtr new_obj = new Object(key); CHECK(hashmap.grow()); - hashmap.insert(*new_obj); + CHECK(hashmap.insert(*new_obj)); objects[NumElements - 1] = new_obj; }