memcpy指向char缓冲区的指针

时间:2019-05-10 18:20:46

标签: c++ multithreading job-scheduling

我目前正在尝试Job系统的一些不同实现(基于this文章)。

我要解决的问题是将参数传递给“作业功能”。

这是我的Job定义:

#define JOB_DATA_PADDING_SIZE   44

/** A job function is a function that can be worked on by the job manager */
typedef void( *JobFunction )( struct Job*, const void* );

/// <summary>
/// A job is something that represents work to be done by the thread pool.
/// Contains a pointer to it's work function and a counter to how many jobs
/// still need to be completed.
/// </summary>
struct Job
{
    JobFunction Function;                       // 8 byte
    Job* Parent;                                // 8 byte
    std::atomic<int32_t> UnfinishedJobs;        // 4 byte
    char Padding[ JOB_DATA_PADDING_SIZE ];      // 44 bytes, so that this object fills
                                                // a whole x64 cache line
};

如您所见,有char Padding缓冲区必须存在,以避免虚假共享。我想使用该缓冲区作为一种简单地存储需要传递给用户正在调用的JobFunction的参数的方法。此设置运行良好,但有一个例外:将指针作为参数传递。

当用户转到“创建工作”时,他们在JobManager上调用此函数:

Job * JobManager::CreateJob( JobFunction aFunction, void* args, size_t aSize )
{
    assert( aSize >= 0 && aSize < JOB_DATA_PADDING_SIZE );

    Job* job = AllocateJob();
    job->Function = aFunction;
    job->Parent = nullptr;
    job->UnfinishedJobs.store( 1 );

    // Memcpy the args to the jobs padding
    if ( args != nullptr )
    {
        memcpy( job->Padding, args, aSize );
    }

    return job;
}

如您所见,计划是将用户提供给函数的参数简单地memcpy放入Padding中。这适用于诸如struct之类的事情,实际上适用于小于44个字节大小的任何数据。

我想做的是将memcpy的给定指针插入到该Padding数组中。但是,当我尝试这样做时,遇到了memcpy复制指针处的值,然后将其复制到缓冲区的问题。

有没有办法我可以memcpy实际的指针进入缓冲区?

我曾尝试过uint64_tuintptr_t,但无济于事。

有没有办法做到这一点?我应该完全不对吗?

整个项目都位于GitHub上,如果这也有助于提供更多背景信息。

1 个答案:

答案 0 :(得分:0)

  

有没有一种方法可以将实际的指针存储到缓冲区中?

当然。 Memcpy不在乎它要复制什么。它所做的只是将字节从源位置复制到目标位置。

假设您要复制一个int值。 Memcpy不知道int的值。它只知道位置。因此,您将不得不将该值放入某个内存位置(例如,放入int 变量)中,然后可以给memcpy一个指向它的指针。

extern void* destination_pointer;
int source = getIntValueFromWherever();          // put the value into the source location
size_t n_bytes = sizeof(source);
memcpy(destination_pointer, &source, n_bytes);   // then give memcpy a pointer to it.

但是您想复制一个指针。好吧,这是同一笔交易。您要复制的内容(例如,某些foobar_t*指针)必须存储在某个位置(例如,变量中)。然后,给memcpy指向源和目标位置的指针。

与上面的int示例唯一不同的是source变量的数据类型:

extern void* destination_pointer;
foobar_t* source = getPointerFromWherever();     // put the value into the source location
size_t n_bytes = sizeof(source);
memcpy(destination_pointer, &source, n_bytes);   // then give memcpy a pointer to it.