Порядок создания объектов
От: kuzbas22  
Дата: 14.10.10 23:57
Оценка:
Такая ситуация — есть нативная функция которая возвращает объект скажем objX
у объекта objX есть свойство массив arr, в который складываются объекты objY

Выглядит примерно так:


tiscript::object_ref objX(pVM);
tiscript::array_ref  arr (pVM);

objX.create();
arr. create();
for (int i = 0; i < 10; i++)
{
    tiscript::object_ref objY(pVM);
    objY.create();
    objY.set("ID",    tiscript::v_int(i));
    objY.set("prop2", tiscript::v_int(i * 2));
    arr.push(objY);
}

objX.set("arr", arr);

return objX;


При попытке обратится к свойству объекта objY из массива arr Получил:
Error: Object BrokenHeart([object BrokenHeart]) has no property — ID
Я так полагаю дело в порядке утановки свойств или в чем ?

Есть такое предложение — сделать функцию GCLock(BOOL bLock) — чтобы она блокировала GC полностью, возможно ли такое ?
Re: Порядок создания объектов
От: c-smile Канада http://terrainformatica.com
Дата: 15.10.10 00:52
Оценка:
Здравствуйте, kuzbas22, Вы писали:

K>При попытке обратится к свойству объекта objY из массива arr Получил:

K>Error: Object BrokenHeart([object BrokenHeart]) has no property — ID
K>Я так полагаю дело в порядке утановки свойств или в чем ?

Я не вижу в твоем коде "попытку обратится к свойству объекта objY из массива arr". Как точно это сделано?

BrokenHeart это индикация того что объект был удален в процессе GC. Как правило лечится использованием pinned variables.
Скрорее всего у тебя где-то используется naked value типа:

value t = ...;
arr.push( t ); // may cause GC 
get_prop(t,...); // may cry "BrokenHeart" here as t is not a valid object handle anymore.


K>Есть такое предложение — сделать функцию GCLock(BOOL bLock) — чтобы она блокировала GC полностью, возможно ли такое ?


В твоей функции идет активная аллокация объектов. Если при этом происходит переполнение heap то вызывается GC.
Т.е. не ясно что именно должен делать эта GCLock если памяти не хватат. Генерить exception? Что ты будешь с ним делать?
Re[2]: Порядок создания объектов
От: kuzbas22  
Дата: 15.10.10 08:31
Оценка:
Здравствуйте, c-smile, Вы писали:
CS>Я не вижу в твоем коде "попытку обратится к свойству объекта objY из массива arr". Как точно это сделано?
Это делается из TIS
CS>BrokenHeart это индикация того что объект был удален в процессе GC. Как правило лечится использованием pinned variables.
CS>Скрорее всего у тебя где-то используется naked value типа:

CS>
CS>value t = ...;
CS>arr.push( t ); // may cause GC 
CS>get_prop(t,...); // may cry "BrokenHeart" here as t is not a valid object handle anymore.
CS>

Даже если t — v_int ?
K>>Есть такое предложение — сделать функцию GCLock(BOOL bLock) — чтобы она блокировала GC полностью, возможно ли такое ?
Вот функция целиком:
tiscript::value CModulePref::GetGameStatePacket(tiscript::VM* pVM)
{
    tiscript::object_ref valRet(pVM);
    valRet.create();
    valRet.set("State",        tiscript::v_int(m_GameState.state.eState));
    valRet.set("ActiveUserID", tiscript::v_int(m_GameState.state.nActiveUserID));
    valRet.set("TableID",      tiscript::v_int(m_GameState.state.nTableID));
    
    PrefGameState   pgs = CPrefLogic::ToGameState(m_GameState.state);
    CPrefLogic      pl(pgs);

    tiscript::array_ref valSitOrder(pVM);
    valSitOrder.create();
    for (int i = 0; i < SIZE_OF(m_GameState.state.nSitOrder); i++)
    {
        valSitOrder.push(tiscript::v_int(m_GameState.state.nSitOrder[i]));
    }
    valRet.set("SitOrder", valSitOrder);
    
    tiscript::array_ref valWidow(pVM);
    valWidow.create();
    for (int i = 0; i < SIZE_OF(m_GameState.state.widow); i++)
    {
        valWidow.push(tiscript::v_int(m_GameState.state.widow[i]));
    }
    valRet.set("Widow", valWidow);

    tiscript::array_ref valUserCards(pVM);
    valUserCards.create();
    BYTE* pCards = pl.GetUserCards(GetUserID());
    if (pCards)
    {
        for (int i = 0; i < PREF_MAX_CARDS_PER_USER; i++)
        {
            if (pCards[i])
                valUserCards.push(tiscript::v_int(pCards[i]));
        }
    }
    valRet.set("Cards", valUserCards);
    
    tiscript::array_ref valUsersState(pVM);
    valUsersState.create();

    UserState us[PREF_MAX_USERS_PER_TABLE];
    memset(us, 0, sizeof(us));
    if (m_GameState.state.nSitOrder[0])
    {
        for (int i = 0; i < SIZE_OF(m_GameState.state.nSitOrder); i++)
        {
            int nID = m_GameState.state.nSitOrder[i];
            for (int j = 0; j < SIZE_OF(m_GameState.state.usersState); j++)
            {
                if (m_GameState.state.usersState[j].nID == nID)
                {
                    memcpy(us + i, m_GameState.state.usersState + j, sizeof(UserState));
                }
            }
        }
        for (int i = 0; i < SIZE_OF(us); i++)
        {
            if (us[i].nID == GetUserID())
            {
                rshift(us, SIZE_OF(us), i);
                break;
            }
        }
        //memcpy(m_GameState.state.usersState, us, sizeof(m_GameState.state.usersState));
    }
    else
    {
        memcpy(us, m_GameState.state.usersState, sizeof(us));
    }
    for (int i = 0; i < SIZE_OF(us); i++)
    {
        if (!m_GameState.state.usersState[i].nID)
            continue;

        tiscript::object_ref valUserState(pVM);
        valUserState.create();
        valUserState.set("ID",     tiscript::v_int(us[i].nID));
        valUserState.set("State",  tiscript::v_int(us[i].eState));
        valUsersState.push(valUserState);
    }
    valRet.set("Users",         valUsersState);
    valRet.set("DealerID",      tiscript::v_int(m_GameState.state.nDealerID));
    valRet.set("TradeWinnerID", tiscript::v_int(m_GameState.state.nTradeWinnerID));
    tiscript::array_ref valWhoDeal(pVM);
    valWhoDeal.create();
    BYTE wd[PREF_MAX_USERS_PER_TABLE] = { 0 };
    for (int i = 0; i < SIZE_OF(us); i++)
    {
        for (int j = 0; j < SIZE_OF(m_GameState.state.usersState); j++)
        {
            if (m_GameState.state.usersState[j].nID == us[i].nID)
            {
                wd[i] = m_GameState.state.whodeal[j];
                break;
            }
        }
    }
    rshift(wd, SIZE_OF(wd), 1);
    for (int i = 0; i < SIZE_OF(wd); i++)
    {
        if (wd[i])
            valWhoDeal.push(tiscript::v_int(wd[i]));
    }
    valRet.set("WhoDeal", valWhoDeal);
    tiscript::array_ref valMisereCards(pVM);
    valMisereCards.create();
    for (int i = 0; i < SIZE_OF(m_GameState.state.misereCards); i++)
    {
        valMisereCards.push( tiscript::v_int(m_GameState.state.misereCards[i]) );
    }
    valRet.set("MisereCards", valMisereCards);
    valRet.set("Card4th",    tiscript::v_int(m_GameState.state.n4thCard));
    return valRet;
}

Есть еще обертка для этой функции, которая экспортируется в TIS, вот она, на всякий:

tiscript::value TISAPI tisGetPrefGameState(tiscript::VM* pVM)
{
    tiscript::pinned retVal(pVM);
    retVal = tiscript::v_undefined();
    tiscript::value valRoot;
    try
    {
    tiscript::args(pVM)
        >> tiscript::args::skip // skip 'this' as this is a global function.
        >> tiscript::args::skip // skip 'super'
        >> valRoot;
    }
    catch(tiscript::args::error &e)
    {
        tiscript::throw_error(pVM, e.msg());
        return retVal;
    }
    HELEMENT hRoot = tiscript::get_native_data(valRoot);
    ASSERT(hRoot);
    if (hRoot)
    {
        CAppWnd* pWnd = (CAppWnd*)CAppWnd::GetByRoot(hRoot);
        ASSERT(pWnd);
        if (pWnd)
        {
            ASSERT(pWnd->GetTEP()->GetModule() == E_SM_PREF);
            if (pWnd->GetTEP()->GetModule() == E_SM_PREF)
            {
                CModulePref* pMod = (CModulePref*)pWnd->GetTEP();
                retVal = pMod->GetGameStatePacket(pVM);
            }
        }
    }
    return retVal;
}


И вот TIS:

function updateUsers()
{
    var packet = GetPrefGameState(view.root);
    var n = 0;
    var elUserInfos     = [ self.$(.userPanelL), self.$(.userPanelR) ];
    var elNames        = [ self.$(#idU1Name),   self.$(#idU2Name)   ];
    var elStatus        = [ self.$(p.status_l),  self.$(p.status_r)  ];
    var status_img      = [ "url(../img/status_l.png)",  "url(../img/status_r.png)" ];
    var statusi_img     = [ "url(../img/statusi_l.png)", "url(../img/statusi_r.png)"];
    for (var el in elUserInfos)
    {
        el.style#foreground-image = "url(../img/ava_empty.png)";
    }
    for (var el in elStatus )
    {
        el.style#display = "none";
    }
    for (var i = 0; i < packet.Users.length; i++)
    {
        if (packet.Users[i].ID != GetCurrentUserID())

Последняя строчка — то место на которое указывает инфа из exception
Причем var packet = GetPrefGameState(view.root); я очень активно использую внутри скрипта, практически в каждой функции оно есть.
И что самое странное — поймал я этот exception всего единожды.
CS>В твоей функции идет активная аллокация объектов. Если при этом происходит переполнение heap то вызывается GC.
CS>Т.е. не ясно что именно должен делать эта GCLock если памяти не хватат. Генерить exception? Что ты будешь с ним делать?
С этим все ясно
Re[2]: pinned в array_ref::push
От: kuzbas22  
Дата: 15.10.10 15:18
Оценка:
Вроде удалось решить проблему добавив pinned в array_ref::push сл. образом:
    bool  push(value value)
    {
      pinned pinned_val(vm, value);
      assert(is_set()); 
      
      unsigned l = length();
      val = ni()->set_array_size(vm,val,l + 1);
      return ni()->set_elem(vm,val,l,pinned_val);
    }


Вопрос: можно ли делать pin 2 раза, т.е. если сюда придет который уже запинен, не вызовет ли это каких либо казусов? я просто предположил что pin работает аналогично AddRef..
Если все ок, то может быть внесете эти изменения?
Re[3]: pinned в array_ref::push
От: c-smile Канада http://terrainformatica.com
Дата: 15.10.10 16:40
Оценка: 3 (1)
Здравствуйте, kuzbas22, Вы писали:

K>Вопрос: можно ли делать pin 2 раза, т.е. если сюда придет который уже запинен, не вызовет ли это каких либо казусов? я просто предположил что pin работает аналогично AddRef..

K>Если все ок, то может быть внесете эти изменения?

Забареи отсюда: http://code.google.com/p/tiscript/source/browse/trunk/sdk/include/tiscript.hpp
Re[3]: pinned в array_ref::push
От: c-smile Канада http://terrainformatica.com
Дата: 15.10.10 17:16
Оценка: 3 (1)
Здравствуйте, kuzbas22, Вы писали:

K>Вопрос: можно ли делать pin 2 раза, т.е. если сюда придет который уже запинен, не вызовет ли это каких либо казусов? я просто предположил что pin работает аналогично AddRef..


Можно делать 2 и более раз.

pinned это структура следующего вида:

struct pinned  
{
  pinned* prev, next;
  object* val;
}


т.е. это элемент списка memory locations которые содержат указатели на объекты.
Когда GC перемещает объекты он в том числе идет по этому списку и обновляет значения val.
Re[4]: pinned в array_ref::push
От: kuzbas22  
Дата: 15.10.10 17:42
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, kuzbas22, Вы писали:


K>>Вопрос: можно ли делать pin 2 раза, т.е. если сюда придет который уже запинен, не вызовет ли это каких либо казусов? я просто предположил что pin работает аналогично AddRef..


CS>Можно делать 2 и более раз.


CS>pinned это структура следующего вида:


CS>
CS>struct pinned  
CS>{
CS>  pinned* prev, next;
CS>  object* val;
CS>}
CS>


CS>т.е. это элемент списка memory locations которые содержат указатели на объекты.

CS>Когда GC перемещает объекты он в том числе идет по этому списку и обновляет значения val.

Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.