Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

21

17.01.2008, 18:58

Zitat von »"Deviloper"«


(Mal so als Hinweiß ... es ist sicherlich klasse, dass du sogar die "instance" mit übergeben hast. Doch wo nutzt du die?)


eigentlich nirgens.. kommt wohl noch raus ^^


C-/C++-Quelltext

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
// -------------------------------------------------------------------

// File:    CThread.hpp

// Desc:    Deklaration for thread-class.

// Defs:    CThread.hpp

// -------------------------------------------------------------------

#if !defined _THREAD_HPP_
#define _THREAD_HPP_




// ------------------------------------

// i n c l u d e s

// ------------------------------------

#include <windows.h>





const signed int THREAD_OK              = 0;
const signed int THREAD_CREATING_ERROR  = -1;




// ------------------------------------

// c l a s s

// ------------------------------------

class Thread
{
private:


    // ------------------------------------

    // m e m b e r _ v a r i a b l e s

    // ------------------------------------


    DWORD                   m_dwThreadID;
    HANDLE                  m_hThreadHandle;


public:


    // ------------------------------------

    // m e m b e r _ f u n c t i o n s

    // ------------------------------------


    Thread();
    ~Thread();


    template<typename T> 
    int Test (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, DWORD (WINAPI T::*ThreadProc)(LPVOID), T* instance, LPVOID lpParameter, DWORD dwCreationFlags);
    int     Create      (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags);
    void    Close       ();


        // ------------------------------------

        // a c c e s s _ f u n c t i o n s

        // ------------------------------------


    DWORD               GetThreadID         ()  { return m_dwThreadID; }
    HANDLE              GetThreadHandle     ()  { return m_hThreadHandle; }


}; // class Thread



// -------------------------------------------------------------------

// Name:    Test()

// Desc:    Creates a new thread.

// -------------------------------------------------------------------

template<typename T>
int Thread::Test(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, DWORD (WINAPI T::*ThreadProc)(LPVOID), T* instance, LPVOID lpParameter, DWORD dwCreationFlags)
{
    if((m_hThreadHandle = CreateThread(lpThreadAttributes, dwStackSize, T::ThreadProc, lpParameter, dwCreationFlags, &m_dwThreadID)) == NULL)
        return THREAD_CREATING_ERROR;

    return THREAD_OK;
} // Test()




#endif
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

22

17.01.2008, 19:57

So, jetzt mal vorne weg:

C-/C++-Quelltext

1
2
#if !defined _THREAD_HPP_
#define _THREAD_HPP_
durch _ gekennzeichnete Bezeichner gehörem dem Compiler, die solltest du tunlichst vermeiden zu nutzen!

C-/C++-Quelltext

1
2
const signed int THREAD_OK                = 0;
const signed int THREAD_CREATING_ERROR    = -1; 
Hast du diesen "Style" von Patrick (nix da, unsigned long) kopiert? Nunja, wenn du nur zwei Rückgabewerte hast, wäre eher ein bool etwas. Dann solltest du dir vllt mal exceptions angucken. Die sind wesentlich eleganter als s.g. "Error-Codes".

C-/C++-Quelltext

1
2
{
private: 
überflüssig, da default-access bei Klasse(im Gegensatz zu Strukturen) immer private ist!

Also jetzt mal alles von vorne!!! :)

C-/C++-Quelltext

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
#if !defined(THREAD_HPP__INCLUDED)
#define THREAD_HPP__INCLUDED

#if (_MSC_VER >= 1300)
#pragma once
#endif // (_MSC_VER >= 1300)


#include <windows.h>

class thread
{
    ::DWORD     m_id;
    ::HANDLE    m_handle;
    
public:
    void run();
    void stop();

public:
    ::DWORD get_id() const { return m_id; }
    ::HANDLE const& get_handle() const { return m_handle; }
};


#endif // THREAD_HPP__INCLUDED
erstmal die Grundstruktur unserer Klasse. Natürlich kann es sein, das wir gleich run noch ein paar Parameter anfügen müssen ...

Naja letztenendes sollte es so gehen:

C-/C++-Quelltext

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
#if !defined(THREAD_HPP__INCLUDED)
#define THREAD_HPP__INCLUDED

#if (_MSC_VER >= 1300)
#pragma once
#endif // (_MSC_VER >= 1300)


#include <windows.h>

template<typename obj_type, typename result_type, typename param_first, typename param_second>
class thread
{
    ::DWORD     m_id;
    ::HANDLE    m_handle;
    
    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct procedure
    {
        obj_type& obj;
        param_first& first;
        param_second& second;
        typedef result_type (obj_type::*fnPtr)(param_first&, param_second&);
        fnPtr ptr_func;
        procedure(obj_type& obj, fnPtr ptr_func, param_first& first, param_second& second)
            : obj(obj), ptr_func(ptr_func), first(first), second(second)
        {}

        result_type operator()()
        { return (obj.*ptr_func)(first, second); }
    };
    procedure<obj_type, result_type, param_first, param_second> m_data;

public:
    typedef procedure<obj_type, result_type, param_first, param_second> procedure_t;

    thread(procedure_t const& data)
        : m_data(data)
    {}

public:
    void run(__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL, __in SIZE_T dwStackSize = 0, __in DWORD dwCreationFlags = 0)
    {
        if ((m_handle = ::CreateThread(lpThreadAttributes, dwStackSize, &thread::_thread_proc, &m_data, dwCreationFlags, &m_id)) == NULL)
            throw std::runtime_error("thread could not be created");
    }
    void stop()
    {
        if (m_handle != NULL) ::CloseHandle(m_handle);
    }

private:
    static DWORD WINAPI _thread_proc(__in  LPVOID ptr_data)
    {
        (*static_cast<procedure_t*>(ptr_data))();
        return S_OK; 
    }

public:
    ::DWORD get_id() const { return m_id; }
    ::HANDLE const& get_handle() const { return m_handle; }
};


#endif // THREAD_HPP__INCLUDED
.

C-/C++-Quelltext

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
#include "thread.hpp"

struct bar
{
    void foo(int& a, int& b)
    { std::clog << "thread procedure called! (a := " << a++ << ", b := " << b++ << ")" << std::endl; }
};

// easy reading ...

typedef thread<bar, void, int, int> thread_bar;

int main()()
{
    bar inst;
    int a(0);
    int b(1);
    // set function pointer to call

    thread_bar::procedure_t data(inst, &bar::foo, a, b); 
    // create thread

    thread_bar my_thread(data);
    // start thread

    my_thread.run();
    // stop thread

    my_thread.stop();
}

;) Okay wenn du das nicht verstehst, kann ich das verstehen :D
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

23

17.01.2008, 20:20

um das jetzt richtigzustellen:

ich muss DAS ALLES verstehen, wenn ich einer funktion eine funktion als parameter übergeben will, die diesen parameter einer weiteren funktion übergibt..? O_o
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

24

17.01.2008, 21:31

nein musst du nicht.

ich lös das z.B. so:

C-/C++-Quelltext

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
// threading.h


#ifndef THREADING_H
#define THREADING_H


#if defined _MSC_VER && _MSC_VER >= 1020
#pragma once
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

namespace Threading
{

  class Threaded
  {
  public:
    virtual int main() = 0;
    virtual ~Threaded() {};
  };

  class Thread
  {
  private:
    HANDLE handle;
    static DWORD WINAPI ThreadProc(void* t);
  public:

    class creation_failed : public std::exception
    {
    public:
      const char* what() const throw() { return "error creating thread"; }
    };

    Thread() : handle(GetCurrentThread()) {}
    Thread(Threaded& start);

    void join() const { WaitForSingleObject(handle, INFINITE); }

    static void yield() { Sleep(0); }
    static void sleep(int ms) { Sleep(ms); }

  };

}

// threading.cpp


#include "threading.h"


DWORD WINAPI Threading::Thread::ThreadProc(void* t)
{
  return static_cast<Threaded*>(t)->main();
}

Threading::Thread::Thread(Threaded& start)
{
  DWORD id;
  if( (handle = CreateThread(0, 0, &ThreadProc, &start, 0, &id)) == 0 )
    throw creation_failed();
}


alles was in nem thread laufen soll wird von Threading::Threaded abgeleitet.

dann kannst du z.b. sowas machen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
class frmServer : public Threading::Threaded
{
  // ...

public:
  int main();
};

// ...


frmServer server;
Threading::Thread ServerThread(server);


diese lösung ist meistens recht brauchbar...

25

17.01.2008, 21:32

C-/C++-Quelltext

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
#if !defined(FUNCTOR_HPP__INCLUDED)
#define FUNCTOR_HPP__INCLUDED

#if (_MSC_VER >= 1300)
#pragma once
#endif // (_MSC_VER >= 1300)


namespace functor
{
    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun_ref
    {
        obj_type& obj;
        param_first& first;
        param_second& second;
        typedef result_type (obj_type::*fnPtr)(param_first&, param_second&);
        fnPtr ptr_func;
        mem_fun_ref(obj_type& obj, fnPtr ptr_func, param_first& first, param_second& second)
            : obj(obj), ptr_func(ptr_func), first(first), second(second)
        {}

        result_type operator()()
        { return (obj.*ptr_func)(first, second); }
    };

    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun_ref_const
    {
        obj_type& obj;
        param_first& first;
        param_second& second;
        typedef result_type (obj_type::*fnPtr)(param_first&, param_second&) const;
        fnPtr ptr_func;
        mem_fun_ref_const(obj_type& obj, fnPtr ptr_func, param_first& first, param_second& second)
            : obj(obj), ptr_func(ptr_func), first(first), second(second)
        {}

        result_type operator()() const
        { return (obj.*ptr_func)(first, second); }
    };

    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun
    {
        obj_type& obj;
        param_first const& first;
        param_second const& second;
        typedef result_type (obj_type::*fnPtr)(param_first const&, param_second const&);
        fnPtr ptr_func;
        mem_fun(obj_type const& obj, fnPtr ptr_func)
            : obj(obj), ptr_func(ptr_func), first(first), second(second)
        {}

        result_type operator()()
        { return (obj.*ptr_func)(first, second); }
    };

    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun
    {
        obj_type& obj;
        param_first const& first;
        param_second const& second;
        typedef result_type (obj_type::*fnPtr)(param_first const&, param_second const&) const;
        fnPtr ptr_func;
        mem_fun_const(obj_type const& obj, fnPtr ptr_func, param_first const& first, param_second const& second)
            : obj(obj), ptr_func(ptr_func), first(first), second(second)
        {}

        result_type operator()() const
        { return (obj.*ptr_func)(first, second); }
    };
}; // functor


#endif // FUNCTOR_HPP__INCLUDED
wäre ne Möglichkeit. Wobei das ist ja so nicht der Funktor im klassischen Sinne. Das wäre dann eher so:

C-/C++-Quelltext

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
#if !defined(FUNCTOR_HPP__INCLUDED)
#define FUNCTOR_HPP__INCLUDED

#if (_MSC_VER >= 1300)
#pragma once
#endif // (_MSC_VER >= 1300)


namespace functor
{
    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun_ref
    {
        obj_type& obj;
        typedef result_type (obj_type::*fnPtr)(param_first&, param_second&);
        fnPtr ptr_func;
        mem_fun_ref(obj_type& obj, fnPtr ptr_func)
            : obj(obj), ptr_func(ptr_func)
        {}

        result_type operator()(param_first& first, param_second& second)
        { return (obj.*ptr_func)(first, second); }
    };

    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun_ref_const
    {
        obj_type& obj;
        typedef result_type (obj_type::*fnPtr)(param_first&, param_second&) const;
        fnPtr ptr_func;
        mem_fun_ref_const(obj_type& obj, fnPtr ptr_func)
            : obj(obj), ptr_func(ptr_func)
        {}

        result_type operator()(param_first& first, param_second& second) const
        { return (obj.*ptr_func)(first, second); }
    };

    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun
    {
        obj_type& obj;
        typedef result_type (obj_type::*fnPtr)(param_first const&, param_second const&);
        fnPtr ptr_func;
        mem_fun(obj_type const& obj, fnPtr ptr_func)
            : obj(obj), ptr_func(ptr_func)
        {}

        result_type operator()(param_first const& first, param_second const& second)
        { return (obj.*ptr_func)(first, second); }
    };

    template<typename obj_type, typename result_type, typename param_first, typename param_second>
    struct mem_fun
    {
        // instance

        obj_type& obj;
        // member-function-pointer

        typedef result_type (obj_type::*fnPtr)(param_first const&, param_second const&) const;
        fnPtr ptr_func;
        mem_fun_const(obj_type const& obj, fnPtr ptr_func)
            : obj(obj), ptr_func(ptr_func)
        {}
        // to enable mem_fun()(first, second)

        result_type operator()(param_first const& first, param_second const& second) const
        { return (obj.*ptr_func)(first, second); }
    };
}; // functor


#endif // FUNCTOR_HPP__INCLUDED
beim letzten steht ein entsprechender Kommentar dran, wofür was ist.

Anwendung:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
#include <functor.hpp>

struct foo
{
    unsigned long bar(std::size_t first, unsigned long second) const { return  std::clog << first << ", " << second << std::endl, first + second; }
};

int main()
{
    foo inst;
    functor::mem_fun_const(inst, &foo::bar)(10, 10UL);
}
fertig! :)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

26

17.01.2008, 21:33

sry, aber für nen C++ anfänger is das imo mit sicherheit nicht sehr hilfreich...

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

27

17.01.2008, 21:53

Zitat von »"$nooc"«


Fehler 1 versteh ich absolut nicht.. ich frag mich wieso der compiler jetzt schon weiss dass ich der funktion ein objekt vom typ frmServer übergeben werde O_o


Dein Problem ist das hier:

C-/C++-Quelltext

1
CreateThread(lpThreadAttributes, dwStackSize, &T::ThreadProc, lpParameter, dwCreationFlags, &m_dwThreadID)) == NULL)


Augenmerk auf &T::ThreadProc... :p
@D13_Dreinig

p0llux

Treue Seele

Beiträge: 101

Wohnort: Aachen

Beruf: HiWi (theo. Inf.)

  • Private Nachricht senden

28

18.01.2008, 10:08

Erster Treffer in Google: http://www.newty.de/fpt/index.html. Da steht nun echt ALLES was man dazu nur wissen kann.

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

29

19.01.2008, 10:22

ich werd das heute versuchen zu implementieren wenn es sich zeitlich ausgeht, dann meld ich mich nochmal :D

danke leute für die hilfe
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

30

21.01.2008, 23:50

eine frage..

kann man typedef in einer klasse verwenden?
ich würde gern einen datentyp schreiben, der als pointer zu einer memberfunktion dient.

von www.newty.de hab ich das:

C-/C++-Quelltext

1
typedef DWORD WINAPI (frmServer::*ptrToThreadProc) (LPVOID);



schreib ich das in die klasse, oder wie macht man sowas.. sry das is neuland für mich..



edit:

ah.. ich glaub ich hab das so ca. verstanden.. mein problem ist jetzt allerdings follgendes..

ich weiss nicht genau was eine calling convention wirklich ist aber ich brauch einen funktionspointer auf eine funktion mit der signatur

C-/C++-Quelltext

1
DWORD WINAPI (frmServer::*ptrToThreadProc) (LPVOID);

wenn ich mir solch einen pointer schreibe, dann spuckt der compiler folgenden fehler aus:

Zitat


Fehler 2 error C2065: 'ptrToThreadProc': nichtdeklarierter Bezeichner
Fehler 1 error C2059: Syntaxfehler: '('



wenn ich WINAPI weglasse, dann hab ich zwar einen pointer, aber dann kann ich ihn nicht mehr auf

C-/C++-Quelltext

1
DWORD WINAPI frmServer::frmServer_ServerThreadProc (LPVOID lpPAram);

zeigen lassen. der fehler lautet dann


C-/C++-Quelltext

1
Fehler  1   error C2440: '=': 'DWORD (__stdcall frmServer::* )(LPVOID)' kann nicht in 'DWORD (__thiscall frmServer::* )(LPVOID)' konvertiert werden



weiss jemand wie ich das lösen kann?
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

Werbeanzeige