ZF_GLOBAL_INITIALIZER_INIT_WITH_LEVEL(ZFThreadTaskRequestDataHolder, ZFLevelZFFrameworkEssential)
{
    _ZFP_ZFThread_wrappedTaskCallback = zfnew(ZFListener);
    *_ZFP_ZFThread_wrappedTaskCallback = ZFCallbackForMethod(ZFMethodAccessFunction(_ZFP_ZFThreadTaskRequestCallback));
    _ZFP_ZFThread_mergeCallbackIgnoreOldTask = zfnew(ZFListener);
    *_ZFP_ZFThread_mergeCallbackIgnoreOldTask = ZFCallbackForMethod(ZFMethodAccessFunction(_ZFP_ZFThreadTaskRequestMergeCallbackIgnoreOldTask));
    _ZFP_ZFThread_mergeCallbackIgnoreNewTask = zfnew(ZFListener);
    *_ZFP_ZFThread_mergeCallbackIgnoreNewTask = ZFCallbackForMethod(ZFMethodAccessFunction(_ZFP_ZFThreadTaskRequestMergeCallbackIgnoreNewTask));
    _ZFP_ZFThread_mergeCallbackDoNotMerge = zfnew(ZFListener);
    *_ZFP_ZFThread_mergeCallbackDoNotMerge = ZFCallbackForMethod(ZFMethodAccessFunction(_ZFP_ZFThreadTaskRequestMergeCallbackDoNotMerge));
    _ZFP_ZFThread_taskDatas = zfAllocWithoutLeakTest(ZFArrayEditable);
}
ZFPROPERTY_TYPE_DECLARE_SERIALIZE_FROM_DEFINE(ZFCallback, ZFCallback)
{
    { // custom serialize logic
        const zfchar *customType = ZFSerializableUtil::checkAttribute(serializableData, ZFSerializableKeyword_ZFCallback_callbackType);
        if(customType != zfnull)
        {
            const ZFSerializableData *customData = ZFSerializableUtil::checkElementByCategory(serializableData, ZFSerializableKeyword_ZFCallback_callbackData);
            if(customData == zfnull)
            {
                ZFSerializableUtil::errorOccurred(outErrorHintToAppend, outErrorPos, serializableData,
                    zfText("missing %s"), ZFSerializableKeyword_ZFCallback_callbackData);
                return zffalse;
            }

            ZFCallbackSerializeCustomSerializeCallback serializeCallback = ZFCallbackSerializeCustomTypeGet(customType);
            if(serializeCallback == zfnull)
            {
                ZFSerializableUtil::errorOccurred(outErrorHintToAppend, outErrorPos, serializableData,
                    zfText("no such callback custom serialize type: %s"), customType);
                return zffalse;
            }
            if(!serializeCallback(result, *customData, outErrorHintToAppend, outErrorPos))
            {
                return zffalse;
            }
            result.callbackSerializeCustomTypeSet(customType);
            result.callbackSerializeCustomDataSet(customData);

            serializableData.resolveMark();
            return zftrue;
        }
    }

    if(zfscmpTheSame(serializableData.itemClass(), ZFSerializableKeyword_null))
    {
        result = ZFCallbackNull();
        serializableData.resolveMark();
        return zftrue;
    }
    if(ZFSerializableUtil::requireSerializableClass(ZFPropertyTypeId_ZFCallback, serializableData, outErrorHintToAppend, outErrorPos) == zfnull)
    {
        return zffalse;
    }

    const ZFSerializableData *methodData = ZFSerializableUtil::requireElementByCategory(serializableData, ZFSerializableKeyword_ZFCallback_method, outErrorHintToAppend, outErrorPos);
    if(methodData == zfnull)
    {
        return zffalse;
    }
    const ZFMethod *method = zfnull;
    if(!ZFMethodFromSerializableData(method, *methodData, outErrorHintToAppend, outErrorPos))
    {
        return zffalse;
    }

    if(method->ownerClass() == zfnull)
    {
        result = ZFCallbackForMethod(method);
    }
    else if(method->methodIsStatic())
    {
        result = ZFCallbackForMethod(method);
    }
    else
    {
        ZFSerializableUtil::errorOccurred(outErrorHintToAppend, outErrorPos, serializableData,
            zfText("member method callback is not supported"));
        return zffalse;
    }

    serializableData.resolveMark();
    return zftrue;
}