【发布时间】:2019-10-23 08:37:30
【问题描述】:
我开发了一个阻塞队列类如下
class Blocking_queue
{
public:
Blocking_queue();
int put(void* elem, size_t elem_size);
int take(void* event);
unsigned int get_size();
private:
typedef struct element
{
void* elem;
size_t elem_size;
struct element* next;
}element_t;
std::mutex m_lock;
std::condition_variable m_condition;
unsigned int m_size;
element_t* m_head;
element_t* m_tail;
};
我希望类尽可能通用,因此我使用了一个 void 指针,该指针在元素添加到队列时分配,从队列中删除时释放。
int Blocking_queue::take(void* event)
{
element_t* new_head = NULL;
int ret = 0;
// Queue empty
if(nullptr == m_head)
{
// Wait for an element to be added to the queue
std::unique_lock<std::mutex> unique_lock(m_lock);
m_condition.wait(unique_lock);
}
if(nullptr == realloc(event, m_head->elem_size))
{
ret = -1;
}
else
{
// Take element from queue
memcpy(event, m_head->elem, m_head->elem_size);
ret = m_head->elem_size;
new_head = m_head->next;
free(m_head->elem);
free(m_head);
m_head = new_head;
if(nullptr == m_head)
{
m_tail = nullptr;
}
m_size -= 1;
}
return ret;
}
如果队列为空,take() 函数将在 m_condition 上等待,直到添加新元素。
在释放元素之前,必须提供指针event 来复制元素的内容。
为了确保给定的指针具有正确的大小来复制元素的内容,我重新分配了指针及其大小。
我遇到的问题是它不允许传递函数的语言环境变量,因为它是在堆栈上分配的。
所以如果我做这样的事情
void function()
{
unsigned int event = 0;
queue->take(&event);
}
我将在 realloc 上遇到 invalid old size 错误。
所以如果我传递一个空指针或一个堆分配的变量,它会工作,但如果我传递一个堆栈变量地址,它就不会。
有没有办法允许将堆栈变量地址传递给take()函数?
【问题讨论】:
-
如果有什么伤害,不要这样做。你的设计完全错误。
-
typedef struct element-- 在 C++ 中不需要typedef struct。您只需要struct element。其次,我希望类尽可能通用——如果元素是非 POD 类型,例如std::string,你的类将如何工作?使用malloc、realloc等将不起作用。这看起来像是使用C构造的尝试,期望C的工作方式与C++ w.r.t 相同。动态创建实例并处理这些实例。在 C++ 中通过使用模板来实现“通用”。 -
玩得开心spurious wakeups
标签: c++ heap-memory stack-memory memory-reallocation