Pretty much what the title says. I'm trying to avoid using the stack for some rather large buffers that are used only shortly and temporarily (convert a hex array to a string so it can be printed, for example) and then garbage collecting the event. Is this ok as long as I remember to garbage collect and not do it too much?
For example:
SomeLargeEvt *evt = Q_NEW(SomeLargeEvt, SOME_SIG);
.. do stuff with evt->dataBuf[100] ...
..
..
.. Finish up ..
QF_gc( evt );
Is this safe or am I playing with fire?
Last edit: Harry Rostovtsev 2015-08-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Instead I would use the QMPool facility directly. This is exactly why this facility is provided in the framework. It is less overhead than allocating dynamic events, but still, the memory-pool operations are thread-safe (i.e., are protected by critical sections).
You can allocate raw memory block via QMPool_get() and release the block via QMPool_put(). Before using a pool, you need to initialize it with QMPool_init().
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Correct me if i'm wrong, but, Q_NEW aren't really dynamic. In main of program that use QP, I declare queue storage like this :
//where MyClassEvt inherit from QP::QEvtstaticQF_MPOOL_EL(Evt::MyClassEvt)l_myClassEvtSto[10];
So when i'm doing Q_NEW, it's not really dynamic, what's is the perk of QMPool ? I found the implentation in PSiCC2 book, but no app notes or something like that. I'm doing I lot of Q_NEW in my application, since it does not doing any malloc/free I can't see where it's dangerous. The only thing that are dangerous is the fact that when you do :
then you don't execute the ctor of std::string class when Q_NEW is performed, it's perfectly normal but can be confusing for some people. (and yes std::string is a bad example).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Is there an example of initializing and using QMPool? I seem to be having a problem setting it up. My code is below:
#defineQM_MEMPOOL_SIZE512staticQMPooll_nativeMemPoolSto[QM_MEMPOOL_SIZE];intmain(void){QF_init();/* initialize the framework and the underlying RT kernel *//* initialize the general memory pool */QMPool_init(l_nativeMemPoolSto,sizeof(l_nativeMemPoolSto),sizeof(l_nativeMemPoolSto[0]),QM_MEMPOOL_SIZE);....etc...}
I get a warning:
4: warning: passing argument 2 of 'QMPool_init' makes pointer from integer without a cast [enabled by default]
../Common/sys/qpc_5.3.1/include/qmpool.h:151:6: note: expected 'void * const' but argument is of type 'unsigned int'
If I do the following, it compiles with no errors or warnings but this doesn't look quite
right:
#defineQM_MEMPOOL_SIZE512staticQMPooll_nativeMemPoolSto[QM_MEMPOOL_SIZE];intmain(void){QF_init();/* initialize the framework and the underlying RT kernel *//* initialize the general memory pool */QMPool_init(&l_nativeMemPoolSto[QM_MEMPOOL_SIZE],l_nativeMemPoolSto,QM_MEMPOOL_SIZE,sizeof(l_nativeMemPoolSto[0]));....etc...}
Above code seems to run but before I get too far with this (start using put() and get() ), is above correct?
Is there an example anywhere of how to correctly initialize the memory pool like this? The port example seems to take 2 storage arrays which makes no sense for my application:
/* Package-scope objects ---------------------------------------------------*/QF_EPOOL_TYPE_QF_pool_[QF_MAX_EPOOL];/* allocate the event pools */uint8_tQF_maxPool_;/* number of initialized event pools *//*..........................................................................*/voidQF_poolInit(void*constpoolSto,uint32_tconstpoolSize,uint32_tconstevtSize){/* cannot exceed the number of available memory pools */Q_REQUIRE(QF_maxPool_<(uint8_t)Q_DIM(QF_pool_));/* please initialize event pools in ascending order of evtSize: */Q_REQUIRE((QF_maxPool_==(uint8_t)0)||(QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - (uint8_t)1])<(QEvtSize)evtSize));/* perfom the platform-dependent initialization of the pool */QF_EPOOL_INIT_(QF_pool_[QF_maxPool_],poolSto,poolSize,evtSize);++QF_maxPool_;/* one more pool */}
Last edit: Harry Rostovtsev 2015-08-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hiere is an anotated example of initializing two memory pools:
QMPool myMemPool1; /* memory pool object #1 (global) */static uint8_t memPoolSto1[512]; /* storage for a memory pool #1 */QMPool myMemPool2; /* memory pool object #2 (global) */static uint8_t memPoolSto2[1024]; /* storage for a memory pool #2 */QMPool_init(&myMemPool1, memPoolSto1, sizeof(memPoolSto1), 10U); /* blocks of 10 bytes each */QMPool_init(&myMemPool2, memPoolSto2, sizeof(memPoolSto2), 25U); /* blocks of 25 bytes each */
As you can see, the object-oriented class pattern is used consistently here. The first argument to the QMPool_init() call is a pointer to a QMPool instance. The three remaining arguments are the storage for the pool, the size of this storage (in bytes), and the block-size of this pool (in bytes).
And here are examples of using the pools:
void *block1 = QMPool_get(&myMemPool1, 0U); /* asserts on empty pool *//* block1 is guaranteed to be not NULL */
~ ~ ~
QMPool_put(&myMemPool1, block1);
void *block2 = QMpool_get(&myMemPool2, 5U); /* non-asserting version */if (block2 != (void *)0) { /* allocation succeeded? */
~ ~ ~
}
~ ~ ~
QMPool_put(&myMemPool2, block2);
I hope that these examples make sense to you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, these make sense. Thank you. I was WAY off :)
Quick question about the sizes of the pools:
Does the 10U and 25U mean that there are 10 pools of 512 bytes and 25 pools 1024 bytes or does that mean that there is a max of 512 bytes and 1024 bytes in the pool and I can allocate a max of 10 blocks and 25 blocks of whatever size as long as they are smaller than the total storage of the pools?
Last edit: Harry Rostovtsev 2015-08-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The memory pools managed by the QMPool class are fixed block-size pools. The block-size of each pool must be determined at initialization and cannot be changed later.
So, for example, a pool initialized with block-size of 10U will contain blocks of at least 10-bytes each. I'm saying "at least", because the QMPool_init() function tries to align all blocks at the (void*) pointer boundary (so the block size must be a muliple of sizeof(void*)).
Consequently, the number of blocks in the pool is the size of the provided storage divided by the (rounded-up) block-size.
In the previous examples, it might work out that myMemPool1 with storage size 512 bytes will have block size of 12 bytes (10U rounded up to 12, assuming sizeof(void*)==4), so it will hold 85 blocks and will have 4 bytes unused.)
Similarly, myMemPool2 with storage size 1024 bytes will have block size of 28 bytes (25U rounded up to 28), so it will hold 36 blocks and will have 16 bytes unused.)
Again, I hope that this makes sense to you.
Last edit: Quantum Leaps 2015-08-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Pretty much what the title says. I'm trying to avoid using the stack for some rather large buffers that are used only shortly and temporarily (convert a hex array to a string so it can be printed, for example) and then garbage collecting the event. Is this ok as long as I remember to garbage collect and not do it too much?
For example:
SomeLargeEvt *evt = Q_NEW(SomeLargeEvt, SOME_SIG);
.. do stuff with evt->dataBuf[100] ...
..
..
.. Finish up ..
QF_gc( evt );
Is this safe or am I playing with fire?
Last edit: Harry Rostovtsev 2015-08-14
I wouldn't use dynamic events.
Instead I would use the QMPool facility directly. This is exactly why this facility is provided in the framework. It is less overhead than allocating dynamic events, but still, the memory-pool operations are thread-safe (i.e., are protected by critical sections).
You can allocate raw memory block via QMPool_get() and release the block via QMPool_put(). Before using a pool, you need to initialize it with QMPool_init().
Fantastic! Thanks for your help, Miro.
Correct me if i'm wrong, but, Q_NEW aren't really dynamic. In main of program that use QP, I declare queue storage like this :
So when i'm doing Q_NEW, it's not really dynamic, what's is the perk of QMPool ? I found the implentation in PSiCC2 book, but no app notes or something like that. I'm doing I lot of Q_NEW in my application, since it does not doing any malloc/free I can't see where it's dangerous. The only thing that are dangerous is the fact that when you do :
and MyClassEvt is like that
then you don't execute the ctor of std::string class when Q_NEW is performed, it's perfectly normal but can be confusing for some people. (and yes std::string is a bad example).
Is there an example of initializing and using QMPool? I seem to be having a problem setting it up. My code is below:
I get a warning:
4: warning: passing argument 2 of 'QMPool_init' makes pointer from integer without a cast [enabled by default]
../Common/sys/qpc_5.3.1/include/qmpool.h:151:6: note: expected 'void * const' but argument is of type 'unsigned int'
If I do the following, it compiles with no errors or warnings but this doesn't look quite
right:
Above code seems to run but before I get too far with this (start using put() and get() ), is above correct?
Is there an example anywhere of how to correctly initialize the memory pool like this? The port example seems to take 2 storage arrays which makes no sense for my application:
Last edit: Harry Rostovtsev 2015-08-18
Hiere is an anotated example of initializing two memory pools:
As you can see, the object-oriented class pattern is used consistently here. The first argument to the
QMPool_init()call is a pointer to aQMPoolinstance. The three remaining arguments are the storage for the pool, the size of this storage (in bytes), and the block-size of this pool (in bytes).And here are examples of using the pools:
I hope that these examples make sense to you.
Yes, these make sense. Thank you. I was WAY off :)
Quick question about the sizes of the pools:
Does the 10U and 25U mean that there are 10 pools of 512 bytes and 25 pools 1024 bytes or does that mean that there is a max of 512 bytes and 1024 bytes in the pool and I can allocate a max of 10 blocks and 25 blocks of whatever size as long as they are smaller than the total storage of the pools?
Last edit: Harry Rostovtsev 2015-08-18
The memory pools managed by the
QMPoolclass are fixed block-size pools. The block-size of each pool must be determined at initialization and cannot be changed later.So, for example, a pool initialized with block-size of 10U will contain blocks of at least 10-bytes each. I'm saying "at least", because the
QMPool_init()function tries to align all blocks at the (void*) pointer boundary (so the block size must be a muliple ofsizeof(void*)).Consequently, the number of blocks in the pool is the size of the provided storage divided by the (rounded-up) block-size.
In the previous examples, it might work out that
myMemPool1with storage size 512 bytes will have block size of 12 bytes (10U rounded up to 12, assumingsizeof(void*)==4), so it will hold 85 blocks and will have 4 bytes unused.)Similarly,
myMemPool2with storage size 1024 bytes will have block size of 28 bytes (25U rounded up to 28), so it will hold 36 blocks and will have 16 bytes unused.)Again, I hope that this makes sense to you.
Last edit: Quantum Leaps 2015-08-18
Yep. Makes sense. Thanks again.