Re[7]: Узнать как был создан объект...
От: Tujh Голландия  
Дата: 30.06.08 15:15
Оценка:
Здравствуйте, merk, Вы писали:
M>в общем смысле, никакой конструктор не должен иметь кода, делающего данный обьект видимым другим тредам. это не только включение в список.
M>аналогично никакой деструктор не должен иметь кода, делающего невидимым обьект другим тредам.
M>"делание видимым" должно идти отдельной операцией после завершения конструирования обьекта.
M>"делание невидимым" — отдельной операцией до начала деструктурирования обьекта.
Структура несколько инная, если убрать часть макросов, получится следующее
// class thread_t
    //
    sint32 ThreadHelper(thread_t *pThread)
    {
        critical_section_guard_t l_guard(NULL);
        {
            try
            {
                l_guard.setSection(&pThread->m_section);
            }
            catch (...)
            {
                return -1;
            }
            if ( !Assigned( getThreadPool()->find( pThread->getThreadID() ) ) )
            {
                pThread->m_event_state.set();
                return -2;
            }
        }
        l_guard.getSection()->leave();
        pThread->m_bool_run = true;
        pThread->m_event_state.set();
        pThread->execute();
        if (pThread->m_event_state.isSet())
            pThread->m_event_state.reset();
        return 0;
    }
    //
    thread_t::thread_t():
        m_event_state(),
        m_bool_run(false),
        m_bool_pause(false)
    {
        m_pclass_thread = new System::system_thread_t;
    }
    //
    thread_t::~thread_t()
    {
        if (m_bool_pause)
            resume();
        if (m_bool_run)
            m_pclass_thread->terminate();
        pop();
        SafeDelete(m_pclass_thread);
    }
    //
    void thread_t::put()
    {
        if (m_pclass_thread->getThreadID())
            getThreadPool()->put(this);
    }
    //
    void thread_t::pop()
    {
        if (m_pclass_thread->getThreadID())
            getThreadPool()->pop(this);
    }
    //
    void thread_t::execute()
    {
        m_event_state.reset();
        threadMain();
        m_event_state.set();
    }
    //
    void thread_t::threadMain()
    {
    }
    //
    bool thread_t::start()
    {
        //critical_section_guard_t l_guard(&m_section);
        m_section.enter();
        if ( m_pclass_thread->create( reinterpret_cast <void*> (this) ) )
            put();
        m_section.leave();
        m_event_state.wait(5000);
        return m_bool_run;
    }
    //
    bool thread_t::stop()
    {
        critical_section_guard_t l_guard(&m_section);
        {
            uint32 l_result = 0;
            m_bool_run = false;
            l_result = m_event_state.wait(200);
            if (l_result == event_t::waitResult::succeded)
            {
                pop();
                m_pclass_thread->destoy();
                return true;
            }
        }
        return false;
    }
// class thread_pool_t
    //
    thread_pool_t* getThreadPool()
    {
        static thread_pool_t g_threadPool;
        return &g_threadPool;
    }
    //
    thread_pool_t::thread_pool_t()
    {
        m_threads.reserve(32);
    }
    //
    thread_pool_t::~thread_pool_t()
    {
        while (!m_threads.empty())
        {
            if ( Assigned( m_threads.front() ) )
            {
                try
                {
                    m_threads.front()->stop();
                    SafeDelete(m_threads.front());
                }
                catch(...)
                {
                }
            }
            m_threads.erase(m_threads.begin());
        }
    }
    //
    bool thread_pool_t::put(const thread_t *pThread)
    {
        if ( Assigned( find( pThread->getThreadID() ) ) )
            return false;
        critical_section_guard_t l_guard(&m_section);
        {
            thread_t *l_pThread = const_cast <thread_t*> (pThread);
            m_threads.push_back(l_pThread);
        }
        return true;
    }
    //
    thread_t* thread_pool_t::pop(const thread_t *pThread)
    {
        critical_section_guard_t l_guard(&m_section);
        {
            thread_array::iterator l_itThread = std::find(m_threads.begin(), m_threads.end(), pThread);
            if (l_itThread != m_threads.end())
            {
                thread_t *Result = (*l_itThread);
                m_threads.erase(l_itThread);
                return Result;
            }
        }
        return NULL;
    }
    //
    thread_t* thread_pool_t::pop(const uint32 threadID)
    {
        thread_t *Result = const_cast <thread_t*> (find(threadID));
        if ( Assigned( Result ) )
        {
            pop(Result);
            return Result;
        }
        return NULL;
    }

На строке SafeDelete(m_threads.front()), при статическом объекте типа thread, и происходит исключение, которого хочу избежать.
SafeDelete() — это просто функция, в которой вызывается delete, но при этом вызов обернут в блок try...catch
Re[8]: Узнать как был создан объект...
От: merk Россия  
Дата: 30.06.08 15:46
Оценка:
Здравствуйте, Tujh, Вы писали:

код пока не смотрел, нет времени. но!
зачем вам вообще статические треды? это моветон.
не парьтесь и делайте их динамически.

конечно если идет delete на статический обьект, это исключение.
Re[4]: Узнать как был создан объект...
От: Кодт Россия  
Дата: 30.06.08 18:08
Оценка:
Здравствуйте, Tujh, Вы писали:

T>Каждый класс thread при создании записывает указатель на себя в пул (который всегда статический), а при уничтожении удаляет.

T>В пуле реализован определенный функционал по управлению потоками. В частности сделана проверка, не допускающая старт потока, который был удален раньше, чем ОС передала управление в функцию этого потока.
T>В деструкторе пула проверяется существование потока, если поток не был удален, ему отсылается команда на удаление, делается выдержка времени и поток "убивается". Естественно, если я попытаюсь таким образом удалить статический объект — приложение "упадет" на уделении пула.
T>Пока не придумал, как можно архитектурно обойти эту ситуацию и нужна "заплатка" для того, что бы знать какие потоки нужно удалять из пула, а какие нельзя. Или же, как и предложили просто запретить создавать объекты потоков статически.

Самое простое: сделай двухступенчатую деинициализацию.
То есть, перед тем, как убивать пул — вызови функцию его финальной очистки. Со всей осторожностью, потокобезопасностью и прочим, и прочим.
А в деструкторе пула проверь предусловие: о том, что он пуст.
И разумеется, что после финальной очистки никто не имеет права добавляться в пул.

Очень полезно делать это не по atexit (когда отрабатывают деструкторы статических объектов), а незадолго до выхода из главной функции (main(), WinMain(), и т.п.)

class MyThreadPool : noncopyable
{
    enum STAGE
    {
        newborn,
        initializing,
        initialized,
        finalizing,
        finalized
    } stage;
public:
    // конструктор и деструктор - простые как валенки
    MyThreadPool() : stage(newborn) {}
    ~MyThreadPool() { ASSERT(stage == finalized); }
    
    void init()   { ASSERT(stage==newborn);     stage=initializing; .......; stage=initialized; }
    void deinit() { ASSERT(stage==initialized); stage=finalizing;   .......; stage=finalized;   }
    
    void add(Thread* t) { ASSERT(stage==initialized); ..... }
    void remove(Thread* t)
    {
        if(stage==finalizing)
            last_chance_remove(t); // учитываем, что в это время в главном потоке происходит deinit()
        else
            normal_remove(t);
    }
    void normal_remove(Thread* t) { ASSERT(stage==initialized); ...... }
};
MyThreadPool the_thread_pool;

// scope guard
struct InitMyThreadPool : noncopyable
{
    InitMyThreadPool() { the_thread_pool.init(); }
    ~InitMyThreadPool() { the_thread_pool.deinit(); }
};

int main()
{
    try
    {
        InitMyThreadPool init_my_thread_pool;
        .......
        .......
        .......
    }
    catch(...) // без этого мы обретём UB, если кто-то в главном потоке метнёт исключение
    {}
}

Естественно, это эскиз. Сюда нужно добавить всякую атомарность, сделать безопасным реентер (нескольких remove при лавинном удалении, deinit+remove), и прочее, и прочее.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[8]: Узнать как был создан объект...
От: merk Россия  
Дата: 30.06.08 21:41
Оценка:
Здравствуйте, Tujh, Вы писали:


см комменты в коде


  //
T>    sint32 ThreadHelper(thread_t *pThread) //этот код работает в pHThread?
T>    {
T>        critical_section_guard_t l_guard(NULL);
T>        {
T>            try
T>            {
T>                l_guard.setSection(&pThread->m_section);
T>            }
T>            catch (...)
T>            {
T>                return -1;
T>            }
T>            if ( !Assigned( getThreadPool()->find( pThread->getThreadID() ) ) )
T>            {
T>                pThread->m_event_state.set();
T>                return -2;
T>            }
T>        }
T>        l_guard.getSection()->leave(); //!!!странный leave, где enter - непонятно
T>        pThread->m_bool_run = true;
T>        pThread->m_event_state.set();
T>        pThread->execute();            //где стартует сам тред?
T>        if (pThread->m_event_state.isSet())
T>            pThread->m_event_state.reset();
T>        return 0;
T>    }
T>    //
T>    thread_t::thread_t():
T>        m_event_state(),
T>        m_bool_run(false),
T>        m_bool_pause(false)
T>    {
T>        m_pclass_thread = new System::system_thread_t;
T>    }
T>    //
T>    thread_t::~thread_t()
T>    {
T>        if (m_bool_pause)
T>            resume();
T>        if (m_bool_run)
T>            m_pclass_thread->terminate();
T>        pop();                        // нельзя в деструкторе удалять тред из пула. это желательно делать раньше
T>        SafeDelete(m_pclass_thread);  //семантика функции неясна.
T>    }
T>    //
T>    void thread_t::put()
T>    {
T>        if (m_pclass_thread->getThreadID())
T>            getThreadPool()->put(this);
T>    }
T>    //
T>    void thread_t::pop()  //антитезой к put является get, a  к pop - push
T>    {
T>        if (m_pclass_thread->getThreadID())
T>            getThreadPool()->pop(this);
T>    }
T>    //
T>    void thread_t::execute()
T>    {
T>        m_event_state.reset();        // вот тут видимо и нужно ставить  pThread->m_bool_run = true;??
T>        threadMain();
T>        m_event_state.set();
T>    }
T>    //
T>    void thread_t::threadMain()
T>    {
T>    }
T>    //
T>    bool thread_t::start()            // тут стартует физический тред?
T>    {
T>        //critical_section_guard_t l_guard(&m_section);
T>        m_section.enter();
T>        if ( m_pclass_thread->create( reinterpret_cast <void*> (this) ) ) //старт в create? может быть проблема вроде.
T>            put(); //если важно чтобы обьект лег в пул, с гарантиейЮ что тред реально заработал, нужно из
                    //тела этого треда пускать какое-то событие. ждать его и потом уже класть в пул.
                    //зачем внтури критсекции запускать тред - неясно. а put в пуле тредов итак в критсекции.
T>        m_section.leave();
T>        m_event_state.wait(5000); //про событие не понятно, когда оно возникает,  и где результат ожидания.
T>        return m_bool_run;
T>    }
T>    //
T>    bool thread_t::stop()
T>    {
T>        critical_section_guard_t l_guard(&m_section); //непонятно. если это локер его нужно сунуть в блок??? а он выше.
T>        {
T>            uint32 l_result = 0;
T>            m_bool_run = false;
T>            l_result = m_event_state.wait(200);   //суть ожидания этого события не очень ясна.
T>            if (l_result == event_t::waitResult::succeded)
T>            {
T>                pop();
T>                m_pclass_thread->destoy();
T>                return true;
T>            }
T>        }
T>        return false;
T>    }
T>// class thread_pool_t
T>    //
T>    thread_pool_t* getThreadPool()
T>    {
T>        static thread_pool_t g_threadPool;
T>        return &g_threadPool;
T>    }
T>    //
T>    thread_pool_t::thread_pool_t()
T>    {
T>        m_threads.reserve(32);
T>    }
T>    //
T>    thread_pool_t::~thread_pool_t() //этот код выполнятется при завершении задачи.
T>    {
T>        while (!m_threads.empty())
T>        {
T>            if ( Assigned( m_threads.front() ) )
T>            {
T>                try
T>                {
T>                    m_threads.front()->stop();  // тут нет гарантии, что тред остановится. проверки кода ошибки тоже.
T>                    SafeDelete(m_threads.front()); //если тред не остановился, это может упасть??
T>                }
T>                catch(...)
T>                {
T>                }
T>            }
T>            m_threads.erase(m_threads.begin());
T>        }
T>    }
T>    //
T>    bool thread_pool_t::put(const thread_t *pThread)
T>    {
T>        if ( Assigned( find( pThread->getThreadID() ) ) ) //a этот find нужно лочить?
T>            return false;
T>        critical_section_guard_t l_guard(&m_section); //где нужно лочить-то?
T>        {
T>            thread_t *l_pThread = const_cast <thread_t*> (pThread);
T>            m_threads.push_back(l_pThread);
T>        }
T>        return true;
T>    }
T>    //
T>    thread_t* thread_pool_t::pop(const thread_t *pThread)
T>    {
T>        critical_section_guard_t l_guard(&m_section); //локер за блоком?
T>        {
T>            thread_array::iterator l_itThread = std::find(m_threads.begin(), m_threads.end(), pThread);
T>            if (l_itThread != m_threads.end())
T>            {
T>                thread_t *Result = (*l_itThread);
T>                m_threads.erase(l_itThread);
T>                return Result;
T>            }
T>        }
T>        return NULL;
T>    }
T>    //
T>    thread_t* thread_pool_t::pop(const uint32 threadID)
T>    {
T>        thread_t *Result = const_cast <thread_t*> (find(threadID)); //тут лочить не нужно? что за find?
T>        if ( Assigned( Result ) )
T>        {
T>            pop(Result);
T>            return Result;
T>        }
T>        return NULL;
T>    }


короче, код путаный какой-то. если падает только на статических тредах..то откуда они берутся? нужно просто запретить их делать статическими и не заниматься хакингом.
Re[8]: Узнать как был создан объект...
От: merk Россия  
Дата: 30.06.08 22:16
Оценка:
Здравствуйте, Tujh, Вы писали:

T> thread_t::~thread_t()

T> {
T> if (m_bool_pause)
T> resume();
T> if (m_bool_run)
T> m_pclass_thread->terminate();
T> pop();
T> SafeDelete(m_pclass_thread);
T> }
вот тут есть у вас pop();


T> bool thread_t::stop()

T> {
T> critical_section_guard_t l_guard(&m_section);
T> {
T> uint32 l_result = 0;
T> m_bool_run = false;
T> l_result = m_event_state.wait(200);
T> if (l_result == event_t::waitResult::succeded)
T> {
T> pop();
T> m_pclass_thread->destoy();
T> return true;
T> }
T> }
T> return false;
T> }
и тут pop();


T> thread_pool_t::~thread_pool_t()

T> {
T> while (!m_threads.empty())
T> {
T> if ( Assigned( m_threads.front() ) )
T> {
T> try
T> {
T> m_threads.front()->stop();
T> SafeDelete(m_threads.front());
T> }
T> catch(...)
T> {
T> }
T> }
T> m_threads.erase(m_threads.begin());
T> }
T> }

а тут — stop() и SafeDelete, что видимо зовет деструктор? два pop()?
ну ладно, пусть два, в pop есть защита, но зачем тогда pop в деструкторе? вы разве можете деструктурировать ваш тред без стопа?
насколько я понимаю, thread_t::start создает физич. тред, пускает его и кладет себя в пул.
stop видимо должен делать обратное. вынимать себя из пула, останавливать физ тред и убивать его, максимально корректным образом.
а деструктор thread_t просто звать stop, если физ тред жив и все.
но ваш деструктор еще и резьюмит, и терминайтит. и тут место непонятное.
Re[9]: Узнать как был создан объект...
От: Tujh Голландия  
Дата: 01.07.08 04:44
Оценка:
Здравствуйте, merk, Вы писали:
Это не весь код, а только основа, если выкладывать весь будет ооочень много
M>Здравствуйте, Tujh, Вы писали:
M>см комменты в коде
M>
M>  //
T>>    sint32 ThreadHelper(thread_t *pThread) //этот код работает в pHThread?
эта функция указывается при старте треда, т.е. в функции _beginthreadex

T>>            try
T>>            {
T>>                l_guard.setSection(&pThread->m_section);
вот тут и происходит enter в секцию
T>>        l_guard.getSection()->leave(); //!!!странный leave, где enter - непонятно

T>>        pThread->execute();            //где стартует сам тред?
эта функция уже выполняется в отдельном треде, и она объявлена как friend для класса

T>>    thread_t::~thread_t()
T>>    {
T>>        if (m_bool_pause)
T>>            resume();
T>>        if (m_bool_run)
T>>            m_pclass_thread->terminate();
T>>        pop();                        // нельзя в деструкторе удалять тред из пула. это желательно делать раньше
это, так сказать, защита, если тред попытаться удалить без стопа, m_pclass_thread->terminate() ожидающая и тред в любом случае будет удален корректно

T>>        SafeDelete(m_pclass_thread);  //семантика функции неясна.
[ccode]    //
    template <typename _Td>
    inline WIZARD_FUNCTION_(bool) SafeDelete(_Td *p)
    {
        try
        {
            if (Assigned(p))
                delete p;
            p = NULL;
        }
        catch (...)
        {
            p = NULL;
            return false;
        };
        return true;
    };[/ccode]



T>>    void thread_t::pop()  //антитезой к put является get, a  к pop - push
Спасибо, поправлю :)

T>>    void thread_t::execute()
T>>    {
T>>        m_event_state.reset();        // вот тут видимо и нужно ставить  pThread->m_bool_run = true;??
T>>        threadMain();
T>>        m_event_state.set();
T>>    }
Не принципиально мне кажется, но посмотрю, может и действительно лучше сюда перенести.

T>>    //
T>>    bool thread_t::start()            // тут стартует физический тред?
Да
T>>    {
T>>        //critical_section_guard_t l_guard(&m_section);
T>>        m_section.enter();
T>>        if ( m_pclass_thread->create( reinterpret_cast <void*> (this) ) ) //старт в create? может быть проблема вроде.
Объект создается раньше, в конструкторе m_pclass_thread = new System::system_thread_t, а тут просто старт треда.
create названо для удобства, т.к. ОС создает тред :xz: 

T>>            put(); //если важно чтобы обьект лег в пул, с гарантией, что тред реально заработал, нужно из
M>                    //тела этого треда пускать какое-то событие. ждать его и потом уже класть в пул.
M>                    //зачем внтури критсекции запускать тред - неясно. а put в пуле тредов итак в критсекции.
T>>        m_section.leave();
T>>        m_event_state.wait(5000); //про событие не понятно, когда оно возникает,  и где результат ожидания.
T>>        return m_bool_run;
T>>    }
Это событие ожидает старта треда.
Логика такая, при вызове start() создается новый тред, кладется в пул и ожидается в течение 5 сек. старт этого треда.
Если все прошло гладко, в ThreadHelper вновь созданный поток выставляет событие m_event_state и m_bool_run в true,
если поток не создался, он удалит себя из пула (и если при этом ОС с запозданием создаст поток, он тут же завершится,
т.к. отсутствует в пуле). Результат ожидания события тут не так важен, т.к. в m_bool_run вернется состояние потока
true - если поток создан или false - если по каким-то причинам в течение 5 секунд не стартовал.

T>>    //
T>>    bool thread_t::stop()
T>>    {
T>>        critical_section_guard_t l_guard(&m_section); //непонятно. если это локер его нужно сунуть в блок??? а он выше.
В конструкторе и происходит enter в секцию

T>>            l_result = m_event_state.wait(200);   //суть ожидания этого события не очень ясна.
потоку дается 200 мс для нормального завершения, в противном случае считается, что остановить поток не удалось

T>>    //
T>>    thread_pool_t::~thread_pool_t() //этот код выполнятется при завершении задачи.
т.к. класс статический - да
T>>    {
T>>        while (!m_threads.empty())
T>>        {
T>>            if ( Assigned( m_threads.front() ) )
T>>            {
T>>                try
T>>                {
T>>                    m_threads.front()->stop();  // тут нет гарантии, что тред остановится. проверки кода ошибки тоже.
да, нет, т.к. деструктор треда гарантирует его завершение.
T>>                    SafeDelete(m_threads.front()); //если тред не остановился, это может упасть??
может, но хочется надеяться, что в деструкторе предусмотренно все

T>>        if ( Assigned( find( pThread->getThreadID() ) ) ) //a этот find нужно лочить?
нет, лок стоит в самом find, если залочим и тут, получим deadlock

T>>        critical_section_guard_t l_guard(&m_section); //где нужно лочить-то?
T>>        {
T>>            thread_t *l_pThread = const_cast <thread_t*> (pThread);
T>>            m_threads.push_back(l_pThread);
T>>        }
как уже омечалось - лок стоит в конструкторе

T>>        critical_section_guard_t l_guard(&m_section); //локер за блоком?
блок - только для удобства чтения, в деструкторе объект разлочится, а деструктор будет вызван при выходе
из функции.

T>>    //
T>>    thread_t* thread_pool_t::pop(const uint32 threadID)
T>>    {
T>>        thread_t *Result = const_cast <thread_t*> (find(threadID)); //тут лочить не нужно? что за find?
вот тут более чем вероятно моё упущение, спасибо
M>


M>короче, код путаный какой-то.

Есть такое дело, в идеале код должен работать на нескольких платформах, поэтому идет значительная обвязка
дополнительными классами.
M>если падает только на статических тредах..то откуда они берутся?
а кто мешает создать естатический ?
M>нужно просто запретить их делать статическими и не заниматься хакингом.
Как ?
Я не знаю как можно запретить создавать объект статически, если покажите — буду очень признателен.
Re[10]: Узнать как был создан объект...
От: merk Россия  
Дата: 01.07.08 10:06
Оценка: -1
Здравствуйте, Tujh, Вы писали:

M>>короче, код путаный какой-то.

T>Есть такое дело, в идеале код должен работать на нескольких платформах, поэтому идет значительная обвязка
T>дополнительными классами.
M>>если падает только на статических тредах..то откуда они берутся?
T>а кто мешает создать естатический ?
M>>нужно просто запретить их делать статическими и не заниматься хакингом.
T>Как ?
T>Я не знаю как можно запретить создавать объект статически, если покажите — буду очень признателен.

если от thread_t никто не у вас наследует...хотя вроде должен...то можно было бы конструктор и деструктор обьявить как private, а пользователю дать фабрику. то есть нечто, что имеет функцию,
thread_t make_new_thread(..); — она будет делать треды динамически и отдавать экземпляр юзеру.
тогда юзер не сможет сам создать обьект.
и уничтожить, поскольку деструктор приватный.
а фабрика будет френдом для thread_t — она сможет и создавать и уничтожать.

но если пользователь будет наследовать ваш тред и делать свои, переопределяя его "тело" тогда трюк не пройдет. ему нужен открытый или протектед конструктор.

2. возможно сделать рантаймовый контроль, навроде —
переопределить для треда оператор new так, чтобы он в треде ставил признак — динамический в true. а конструктор ставил признак в false. тогда если тред был статическим у него признак будет в false. а если делался через new — true.
и например при включении в пул, проверять признак. если false — страшно ругаться.
а можно не ругаться и переопределить еще и delete. тогда если признак стоит — false — обьект не делитить.
если я не ошибаюсь в C++ переопределенные операторы вроде наследуются. то есть потомки будут эти операторы и вызывать. если не будут — вопросы к страструпу.
Re: CDynamicObject
От: Erop Россия  
Дата: 02.07.08 13:26
Оценка:
Здравствуйте, Tujh, Вы писали:

T>Или, как вариант, можно ли перегрузить оператор new что бы стало возможным это определить?


Пишу из головы, требуется отладка!
Но так, IMHO, будет и просто и ясно и без хаккерства.
class CDynamicObject {
public:

    template<typename T> 
    static T* Create()
    {
        auto_ptr<T> res( new CCreator<T> );
        static_cast<CDynamicObject*>( res.get() )->AfterCtor();
        return res.release(); 
    }
    static void Destroy( CDynamicObject* p )
    {
         if( p == 0 )
             return;
         auto_ptr<CDynamicObject> pp( p );
         p->BeforeDtor();
    }


protected:
    CDynamicObject() {}
    CDynamicObject( const CDynamicObject& ) {}
    virtual ~CDynamicObject() {};
    
    virtual void AfterCtor() {}
    virtual void BeforeDtor() {}

private:
    enum SecretSeed { SS_0 };
    virtual void tryToDefineItForEnableObjectUsing( SecretSeed ) = 0;
    template<typename T> struct CCreator : T { void tryToDefineItForEnableObjectUsing( SecretSeed ) {} };
};
Выводи свои классы из CDynamicObject, и их можно будет создавать только по CDynamicObject::Create<MyClass>, а разрушать только по CDynamicObject::Destroy.
При этом после окончания конструирования объекта у него будет вызван AfterCtor, а перед разрушением BeforeDtor.

Соответсвенно выводи свои нити из CDynamicObject, в AfterCtor регь их в пуле, а в BeforeDtor из пула их вынивмай.
Ну а в деструкторе можно assert проверять, что нить из пула вынута, а в методах, что находится в пуле
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Узнать как был создан объект...
От: Erop Россия  
Дата: 02.07.08 13:28
Оценка:
Здравствуйте, Tujh, Вы писали:

T>Я не знаю как можно запретить создавать объект статически, если покажите — буду очень признателен.

1) Инструкцией/комментом к коду...
2) Так
Автор: Erop
Дата: 02.07.08
попробуй
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: CDynamicObject
От: merk Россия  
Дата: 02.07.08 15:13
Оценка: +1
Здравствуйте, Erop, Вы писали:

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


T>>Или, как вариант, можно ли перегрузить оператор new что бы стало возможным это определить?


E>Пишу из головы, требуется отладка!

а писать надо из сердца!
тогда отладка не потребуется.

... а нельзя ли просто в первой строке main. взвести некий булевский флажок(типа статик поле класса CBaseThread)..что мол статическое конструирование уже закончилось! дальше тока динамическое.
ну ..там и проверять этот флажок в конструкторе, или в засовывании в пул тредов. рантайм проверка соббсно.
ну будет в системе еще одно исключение.
но как сердце зарадуется!
и без наворотов.
Re[3]: CDynamicObject
От: Erop Россия  
Дата: 02.07.08 16:22
Оценка:
Здравствуйте, merk, Вы писали:

M>а писать надо из сердца!

M>тогда отладка не потребуется.
Ну одно из двух.
Или в сердце у тебя холодный расчёт, или в программах нет никакой логики

M>... а нельзя ли просто в первой строке main. взвести некий булевский флажок(типа статик поле класса CBaseThread)..что мол статическое конструирование уже закончилось! дальше тока динамическое.

Увы, нельзя
1) Ещё бывают static in function
2) Ещё бывают автоматические переменные. Их тоже, по идее, надо бы запретить.

M>ну ..там и проверять этот флажок в конструкторе, или в засовывании в пул тредов. рантайм проверка соббсно.

M>ну будет в системе еще одно исключение.
Ну с рантаймом такая беда, что такая проверка и так есть. Насколько я понял топикстартера у него и так все сейчас авостом кончается. Тем не менее он чем-то не доволен вроде бы...

M>но как сердце зарадуется!

M>и без наворотов.
Ну навороты-то не такие уж и грандиозные...
Хотя я, конечно, просто бы запретил
Автор: Erop
Дата: 02.07.08
создавать наследников нити в комментариях к ней. Ну и нашёл бы статические и автоматические объекты просто поиском. Если типов нитей не бесконечно много в программе...

Но топикстартеру, насколько я понял, хотелось бы средство, выраженное на С++
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: CDynamicObject
От: Tujh Голландия  
Дата: 04.07.08 05:45
Оценка: +1
Здравствуйте, Erop, Вы писали:
E>Но топикстартеру, насколько я понял, хотелось бы средство, выраженное на С++
Огромное спасибо всем за ответы!

1) В коментариях к классу (и справке) и так вписано, что статические и экземпляры на стеке создавать нельзя.
2) Смутило как-то, что в BCB2006 (про другие версии не знаю) при попытке создать экземпляры VCL классов статически или на стеке выпадает error при компиляции, мол, "ай-ай-ай, низяяя, только через new (VCL style classes must be constructed using operator new)".

Захотелось хорошего, сделать что-то по подобию, неправильно создал — получи ошибку на этапе компиляции, но это очевидно "compiler magic" Borland`а
Re[5]: CDynamicObject
От: Erop Россия  
Дата: 04.07.08 06:20
Оценка: +1
Здравствуйте, Tujh, Вы писали:

T>Огромное спасибо всем за ответы!

Для "спасибо" тут есть кнопки

T>Захотелось хорошего, сделать что-то по подобию, неправильно создал — получи ошибку на этапе компиляции, но это очевидно "compiler magic" Borland`а

Да, наверное. Ну можэно через химию с абстрактными классами это проэмулировать, если надо. Но надо ли -- смотреть тебе. IMHO сильно необязательно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: CDynamicObject
От: Tujh Голландия  
Дата: 04.07.08 08:13
Оценка: 14 (1) :)
Здравствуйте, Erop, Вы писали:
T>>Огромное спасибо всем за ответы!
E>Для "спасибо" тут есть кнопки
[offtopic]
отспасибкался кнопкой
обычно я разными системами рейтингов на форумах не пользуюсь, ибо считаю это детской забавой, но ни когда не позно изменить свои принципы, тем более тёзке сказать "спасибо" в двойне приятно
[/offtopic]
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.