summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/src-all/ThreadTask.cpp
blob: 1c516f2a3ea15a8971c21d9ad713fbaaf134bc32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* $Id: ThreadTask.cpp $ */
/** @file
 * Implementation of ThreadTask
 */

/*
 * Copyright (C) 2015-2020 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#include <iprt/errcore.h>
#include <iprt/thread.h>

#include "VirtualBoxBase.h"
#include "ThreadTask.h"

#define LOG_GROUP LOG_GROUP_MAIN_THREAD_TASK
#include "LoggingNew.h"

/**
 * Starts the task (on separate thread), consuming @a this.
 *
 * The function takes ownership of "this" instance (object instance which calls
 * this function). And the function is responsible for deletion of "this"
 * pointer in all cases.
 *
 * Possible way of usage:
 * @code{.cpp}
        HRESULT hr;
        SomeTaskInheritedFromThreadTask *pTask = NULL;
        try
        {
            pTask = new SomeTaskInheritedFromThreadTask(this);
            if (!pTask->Init()) // some init procedure
                throw E_FAIL;
        }
        catch (...)
        {
            if (pTask);
                delete pTask;
            return E_FAIL;
        }
        return pTask->createThread(); // pTask is always consumed
   @endcode
 *
 * @sa createThreadWithType
 *
 * @note Always consumes @a this!
 */
HRESULT ThreadTask::createThread(void)
{
    return createThreadInternal(RTTHREADTYPE_MAIN_WORKER);
}


/**
 * Same ThreadTask::createThread(), except it takes a thread type parameter.
 *
 * @param   enmType     The thread type.
 *
 * @note Always consumes @a this!
 */
HRESULT ThreadTask::createThreadWithType(RTTHREADTYPE enmType)
{
    return createThreadInternal(enmType);
}


/**
 * Internal worker for ThreadTask::createThread,
 * ThreadTask::createThreadWithType.
 *
 * @note Always consumes @a this!
 */
HRESULT ThreadTask::createThreadInternal(RTTHREADTYPE enmType)
{
    LogThisFunc(("Created \"%s\"\n", m_strTaskName.c_str()));

    mAsync = true;
    int vrc = RTThreadCreate(NULL,
                             taskHandlerThreadProc,
                             (void *)this,
                             0,
                             enmType,
                             0,
                             m_strTaskName.c_str());
    if (RT_SUCCESS(vrc))
        return S_OK;

    mAsync = false;
    delete this;
    return E_FAIL;
}


/**
 * Static method that can get passed to RTThreadCreate to have a
 * thread started for a Task.
 */
/* static */ DECLCALLBACK(int) ThreadTask::taskHandlerThreadProc(RTTHREAD /* thread */, void *pvUser)
{
    if (pvUser == NULL)
        return VERR_INVALID_POINTER; /* nobody cares */

    ThreadTask *pTask = static_cast<ThreadTask *>(pvUser);

    LogFunc(("Started \"%s\"\n", pTask->m_strTaskName.c_str()));

    /*
     *  handler shall catch and process all possible cases as errors and exceptions.
     */
    pTask->handler();

    LogFunc(("Ended \"%s\"\n", pTask->m_strTaskName.c_str()));

    delete pTask;
    return VINF_SUCCESS;
}