Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cascaded allocator #2113

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bd320b1
can compiled successfully on Windows Plat
smithAchang Sep 3, 2023
37dc8f4
Allocator_Cascaded_Test.cpp增加
smithAchang Sep 3, 2023
c61b9be
add the 2*sum(Allocator of hierarchy) testing case
smithAchang Sep 4, 2023
6166f88
bin/fuzz.pl find trailing whitespace
smithAchang Sep 4, 2023
32d3d1f
bin/fuzz.pl find trailing whitespace 2
smithAchang Sep 4, 2023
e2a5511
compiler error
smithAchang Sep 4, 2023
6835890
dsfdsdfMerge branch 'cascadedAllocator' of github.com:smithAchang/ACE…
smithAchang Sep 4, 2023
150eb7b
use std::vector
smithAchang Sep 4, 2023
089af45
linux compiling error & fix issue
smithAchang Sep 5, 2023
ac87bd4
according the routine of test framework
smithAchang Sep 5, 2023
b71f82d
key design comment for free API
smithAchang Sep 5, 2023
34abb6e
fix space indent & const member field
smithAchang Sep 5, 2023
cf39680
using instead of typedef, will be fitter for template declaration
smithAchang Sep 5, 2023
78e7165
remove duplicate empty lines
smithAchang Sep 5, 2023
e5e55bc
free protected when malloc in constructor failed
smithAchang Sep 5, 2023
00016bf
1. add assert for free API
smithAchang Sep 5, 2023
912d9db
add comments for ACE_NEW fail in constructor
smithAchang Sep 6, 2023
833bc87
Merge branch 'master' into cascadedAllocator
smithAchang Sep 6, 2023
40675b0
fix ""One line, indent is always 2 spaces
smithAchang Sep 7, 2023
148734d
Merge branch 'cascadedAllocator' of github.com:smithAchang/ACE_TAO in…
smithAchang Sep 7, 2023
6e9a17c
for g++ -fno-implicit-templates consideration
smithAchang Sep 8, 2023
d065069
implement the dump API
smithAchang Sep 16, 2023
eba85a4
fix for statement of dump API
smithAchang Sep 16, 2023
1e1862d
fix trailing whitespace
smithAchang Sep 16, 2023
0f26ecb
add hierarchy_.size () for dump API
smithAchang Sep 18, 2023
4a7fcd0
1、fix some coding style using this keyword to distinguish vars
smithAchang Sep 22, 2023
cf686b3
add the pool_sum api
smithAchang Sep 22, 2023
4c27ab0
1、fix constructor description
smithAchang Sep 23, 2023
8210ac0
1、split ACE_NEW* with empty line, the macro function may end the flow
smithAchang Sep 23, 2023
e8d9b51
1、fix unsupported API return nullptr
smithAchang Sep 25, 2023
63e543f
add deeply test case for calloc API
smithAchang Sep 26, 2023
d4e7d14
modify growth strategy to exponential growth when hierarchy grows fo…
smithAchang Sep 29, 2023
874d9cb
keep the consistent to cascaded malloc branch
smithAchang Sep 29, 2023
92066a1
add exception safety for the growth of chunk sum
smithAchang Sep 29, 2023
4a9c114
fix the exception safety for calling vector push_back API
smithAchang Sep 29, 2023
8450156
Using std::unique_ptr will be more exception-safe literally
smithAchang Sep 29, 2023
0c8067c
delete defence codes
smithAchang Sep 29, 2023
cc4053c
delete unused temp stack var
smithAchang Sep 29, 2023
ac5f611
fix invalid document of class
smithAchang Sep 29, 2023
fec93be
fix coding style of comment
smithAchang Oct 8, 2023
42b409e
fix for right const coding style
smithAchang Oct 8, 2023
a837b5d
format using clang-format
smithAchang Oct 8, 2023
c9ead44
fix for coding style of function call
smithAchang Oct 8, 2023
021ef62
optimization for cascaded allocator considering the character that on…
smithAchang Jan 13, 2024
92c3499
Merge branch 'master' into cascadedAllocator
smithAchang Jan 13, 2024
b84e0c4
modify the branch judgement of the last allocator using const var
smithAchang Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions ACE/ace/Malloc_T.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,171 @@ ACE_Dynamic_Cached_Allocator<ACE_LOCK>::free (void * ptr)
this->free_list_.add ((ACE_Cached_Mem_Pool_Node<char> *) ptr);
}

template <class ACE_LOCK>
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::ACE_Cascaded_Dynamic_Cached_Allocator
(size_t initial_n_chunks, size_t chunk_size)
: initial_n_chunks_ (initial_n_chunks),
chunk_size_ (chunk_size)
{
ACE_ASSERT (chunk_size_ > 0);

comb_alloc_ptr tmp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialize tmp

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the temp var will be assigned or call flow is ended by ACE_NEW macro

Should it be initialized?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the temp var will be assigned or call flow is ended by ACE_NEW macro

Should it be initialized?

// If ACE_NEW fails, the hierarchy_ will be reconstructed when malloc API is called.
ACE_NEW (tmp, comb_alloc_type(this->initial_n_chunks_, this->chunk_size_));
smithAchang marked this conversation as resolved.
Show resolved Hide resolved
hierarchy_.push_back(tmp);
}

template <class ACE_LOCK>
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::~ACE_Cascaded_Dynamic_Cached_Allocator ()
{
for (size_t c = 0;
c < hierarchy_.size();
c++)
{
delete hierarchy_[c];
}

hierarchy_.clear();
}

template <class ACE_LOCK> void *
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::malloc (size_t nbytes)
{
// Check if size requested fits within pre-determined size.
if (nbytes > chunk_size_)
return nullptr;

ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, nullptr));

void * ptr = nullptr;

for (size_t c = 0;
c < hierarchy_.size();
c++)
{
ptr = hierarchy_[c]->malloc(nbytes);
if(ptr != nullptr)
break;
}

if(ptr == nullptr)
{
comb_alloc_ptr tmp;
ACE_NEW_RETURN (tmp, comb_alloc_type(this->initial_n_chunks_ * 2 * hierarchy_.size(), this->chunk_size_), nullptr);
hierarchy_.push_back(tmp);
ptr = tmp->malloc(nbytes);
}

return ptr;
}

template <class ACE_LOCK> void *
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::calloc (size_t nbytes,
char initial_value)
{
// Check if size requested fits within pre-determined size.
if (nbytes > chunk_size_)
return nullptr;

// No need any lock.
void *ptr = malloc(nbytes);
if (ptr != nullptr)
ACE_OS::memset (ptr, initial_value, chunk_size_);

return ptr;
}

template <class ACE_LOCK> void *
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::calloc (size_t, size_t, char)
{
ACE_NOTSUP_RETURN (0);
}

template <class ACE_LOCK> void
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::free (void * ptr)
{
ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));

ACE_ASSERT (hierarchy_.size () > 0);

// Use first allocator as a free chunk manager for all allocators when chunk freed.
if (ptr != nullptr && hierarchy_.size () > 0)
hierarchy_[0]->free(ptr);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::remove ()
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::bind (const char *, void *, int)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::trybind (const char *, void *&)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::find (const char *, void *&)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::find (const char *)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::unbind (const char *)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::unbind (const char *, void *&)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::sync (ssize_t, int)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::sync (void *, size_t, int)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::protect (ssize_t, int)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> int
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::protect (void *, size_t, int)
{
ACE_NOTSUP_RETURN (-1);
}

template <class ACE_LOCK> void
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::dump () const
{
#if defined (ACE_HAS_DUMP)
#endif /* ACE_HAS_DUMP */
}

ACE_ALLOC_HOOK_DEFINE_Tmcc (ACE_Malloc_T)

template <class MALLOC> void *
Expand Down
101 changes: 100 additions & 1 deletion ACE/ace/Malloc_T.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* @file Malloc_T.h
*
* @author Douglas C. Schmidt <[email protected]> and
* Irfan Pyarali <[email protected]>
* Irfan Pyarali <[email protected]> and
smithAchang <[email protected]>
*/
//==========================================================================

Expand All @@ -15,6 +16,7 @@

#include "ace/Malloc.h" /* Need ACE_Control_Block */
#include "ace/Malloc_Base.h" /* Need ACE_Allocator */
#include "ace/Null_Mutex.h" /* Need ACE_Null_Mutex */

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
Expand All @@ -24,6 +26,8 @@
#include "ace/Free_List.h"
#include "ace/Guard_T.h"

#include <vector>

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

/**
Expand Down Expand Up @@ -203,6 +207,101 @@ class ACE_Dynamic_Cached_Allocator : public ACE_New_Allocator
size_t chunk_size_;
};

/**
* @class ACE_Cascaded_Dynamic_Cached_Allocator
*
* @brief A fixed-size-based allocator that caches blocks for quicker access,
* but with a hierarchy of cascaded, nested allocators
*
* This class enables caching of dynamically allocated,
* fixed-size chunks. Notice that the @a chunk_size
* must be greater than or equal to <code> sizeof (void*) </code> for
* this to work properly.
*
* Notice that when the latest allocator is empty, the allocator will create a fresh
* @a ACE_Dynamic_Cached_Allocator allocator again with
* <code> init_n_chunks* the sum of current allocators </code> as it's constructor parameter,
* so all the allocators will form a cascaded hierarchy.

* This class can be configured flexibly with different types of
* ACE_LOCK strategies that support the @a ACE_Thread_Mutex and @a
* ACE_Process_Mutex constructor API.
*
* @sa ACE_Dynamic_Cached_Allocator
*/
template <class ACE_LOCK>
class ACE_Cascaded_Dynamic_Cached_Allocator : public ACE_Allocator
{
public:
/// Create a cached memory pool with @a n_chunks chunks
/// each with @a chunk_size size.
ACE_Cascaded_Dynamic_Cached_Allocator (size_t initial_n_chunks, size_t chunk_size);

/// Clear things up.
~ACE_Cascaded_Dynamic_Cached_Allocator ();

/**
* Get a chunk of memory from free list cache. Note that @a nbytes is
* only checked to make sure that it's less or equal to @a chunk_size,
* and is otherwise ignored since malloc() always returns a pointer to an
* item of @a chunk_size size.
*/
virtual void *malloc (size_t nbytes);

/**
* Get a chunk of memory from free list cache, giving them
* @a initial_value. Note that @a nbytes is only checked to make sure
* that it's less or equal to @a chunk_size, and is otherwise ignored
* since calloc() always returns a pointer to an item of @a chunk_size.
*/
virtual void *calloc (size_t nbytes, char initial_value = '\0');

/// This method is a no-op and just returns 0 since the free list
/// only works with fixed sized entities.
virtual void *calloc (size_t n_elem, size_t elem_size, char initial_value = '\0');

/// Return a chunk of memory back to free list cache.
virtual void free (void *ptr);

/// These methods are no-ops.
virtual int remove ();
smithAchang marked this conversation as resolved.
Show resolved Hide resolved
virtual int bind (const char *name, void *pointer, int duplicates = 0);
virtual int trybind (const char *name, void *&pointer);
virtual int find (const char *name, void *&pointer);
virtual int find (const char *name);
virtual int unbind (const char *name);
virtual int unbind (const char *name, void *&pointer);
virtual int sync (ssize_t len = -1, int flags = MS_SYNC);
virtual int sync (void *addr, size_t len, int flags = MS_SYNC);
virtual int protect (ssize_t len = -1, int prot = PROT_RDWR);
virtual int protect (void *addr, size_t len, int prot = PROT_RDWR);
virtual void dump () const;

/// Return the number of chunks available in the hierarchy.
size_t pool_depth ();

/// Returns a reference to the lock used to provide mutual exclusion to
/// the allocator hierarchy.
ACE_LOCK &mutex ();

private:
// Useful STL-style traits.
using comb_alloc_type = ACE_Dynamic_Cached_Allocator<ACE_Null_Mutex>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be ACE_LOCK?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no need because the nested allocator will be protected by container class api

using comb_alloc_ptr = comb_alloc_type*;

/// Synchronization variable for API.
ACE_LOCK mutex_;

/// Remember how we allocate the memory so we can clear things up later.
std::vector<comb_alloc_ptr> hierarchy_;

/// Remember the size of initial n_chunks for creating fresh allocator in future.
const size_t initial_n_chunks_;

/// Remember the size of our chunks for creating fresh allocator in future.
const size_t chunk_size_;
};

/**
* @class ACE_Allocator_Adapter
*
Expand Down
23 changes: 23 additions & 0 deletions ACE/ace/Malloc_T.inl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,29 @@ ACE_Dynamic_Cached_Allocator<ACE_LOCK>::pool_depth ()
return this->free_list_.size ();
}

template <class ACE_LOCK> ACE_INLINE size_t
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::pool_depth ()
{
ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, 0));

size_t pool_depth = 0;

for (size_t c = 0;
smithAchang marked this conversation as resolved.
Show resolved Hide resolved
c < hierarchy_.size();
c++)
{
pool_depth += hierarchy_[c]->pool_depth();
}

return pool_depth;
}

template <class ACE_LOCK> ACE_INLINE ACE_LOCK &
ACE_Cascaded_Dynamic_Cached_Allocator<ACE_LOCK>::mutex ()
{
return this->mutex_;
}

template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ACE_INLINE int
ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ref_counter ()
{
Expand Down
Loading