पोर्टेबल मल्टी-थ्रेडेड एप्लिकेशन बनाने के लिए, मैं ग्लिब लाइब्रेरी का उपयोग करने का सुझाव देता हूं।
ग्लिब एक काफी बड़ा क्रॉस-प्लेटफ़ॉर्म लाइब्रेरी है, जिसमें स्ट्रीम के अलावा, अंतर्राष्ट्रीयकरण के लिए समर्थन, स्ट्रिंग्स, सरणियों, फ़ाइलों, टाइमर के साथ काम करना, और बहुत कुछ शामिल है, जिसमें XML पार्सर और .ini कॉन्फ़िगरेशन फ़ाइलों के लिए समर्थन शामिल है।
इसी समय, यह पुस्तकालय काफी छोटा है और इसमें लगभग कोई निर्भरता नहीं है, जो इसे बिना किसी समस्या के विंडोज परियोजनाओं में शामिल करने की अनुमति देता है, और ग्लिक्स पहले से ही यूनिक्स जैसी प्रणालियों में मौजूद है।
यह विकल्प मुख्य रूप से क्रॉस-प्लेटफॉर्म कंसोल और ग्राफिकल जीटीके अनुप्रयोगों के लिए उपयुक्त है।
थ्रेड प्रोग्रामिंग
अनुप्रयोग में थ्रेड्स का उपयोग करने के लिए, पहली बात यह है कि इनिशियलाइज़ेशन फ़ंक्शन को निष्पादित करना है:
g_thread_init (NULL);
एक नया सूत्र बनाएँ
GThread* g_thread_create (GThreadFunc func, gpointer data, gboolean joinable, GError **error);
मापदंडों का विवरण:
func - फॉर्म के एक प्रोटोटाइप के साथ स्ट्रीम फ़ंक्शन: gpointer GThreadFunc (gpointer data);
डेटा - स्ट्रीम में प्रेषित अतिरिक्त डेटा के लिए एक सूचक, NULL हो सकता है।
शामिल होने योग्य - क्या g_thread_join () के माध्यम से धागे के पूरा होने की उम्मीद करना संभव होगा
त्रुटि - स्ट्रीम बनाते समय त्रुटि का कोड और विवरण, NULL हो सकता है।
वर्तमान धागे के GThread का पता लगाएं
GThread * g_thread_self (शून्य);
थ्रेड प्राथमिकता बदलें:
शून्य g_thread_set_priority (GThread * thread_id, GThreadPriority प्राथमिकता);
मापदंडों का विवरण:
Thread_id - g_thread_create () के माध्यम से थ्रेड बनाते समय प्राप्त संरचना
प्राथमिकता - आरोही क्रम में प्राथमिकता, संभावित विकल्प:
G_THREAD_PRIORITY_LOW
G_THREAD_PRIORITY_NORMAL
G_THREAD_PRIORITY_HIGH
G_THREAD_PRIORITY_URGENT
एक और सूत्र के पूरा होने की प्रतीक्षा करें:
gpointer g_thread_join (GThread * thread_id);
मापदंडों का विवरण:
Thread_id - g_thread_create () के माध्यम से थ्रेड बनाते समय प्राप्त संरचना
फ़ंक्शन स्ट्रीम के पूरा होने तक प्रतीक्षा करेगा, जब वह शामिल होने पर = योग्य हो, और स्ट्रीम फ़ंक्शन को पूरा करने के लिए कोड वापस कर देगा।
Joinable = FALSE के साथ एक थ्रेड बनाते समय, फ़ंक्शन तुरंत अपने निष्पादन को पूरा करेगा और 0 लौटाएगा।
एक उदाहरण:
// ;
gpointer thread_func(gpointer data)
{
printf(" \n");
return 0;
}
int main (int argc, char *argv[])
{
//
g_thread_init(NULL);
//
GThread *thread_id = g_thread_create(thread_func,NULL,TRUE,NULL);
//
g_thread_join(thread_id);
printf(" \n");
return 0;
}
धागा सिंक्रनाइज़ेशन
म्यूटेक्स और सिग्नल (स्थिति) पर विचार करें। अन्य विशिष्ट विधियां हैं, जैसे कि अवरुद्ध बिट्स, लेकिन उनमें से लगभग सभी को म्यूटेक्स और / या संकेतों से बदला जा सकता है।
म्युटेक्स
कोड को साझा करने से बचाने के लिए म्यूटेक्स का उपयोग किया जाता है। यह विंडोज के लिए महत्वपूर्ण अनुभाग का एक एनालॉग है।
जैसे ही एक धागे ने म्यूटेक्स पर कब्जा कर लिया है, अन्य धागे, जब म्यूटेक्स को पकड़ने की कोशिश कर रहे हैं, तो इसके जारी होने का इंतजार करेंगे, इसलिए किसी भी समय केवल एक धागा म्यूटेक्स के अंदर कोड तक पहुंच सकता है।
म्यूटेक्स बनाना:
GMutex * g_mutex_new ();
म्यूटेक्स लॉक:
शून्य g_mutex_lock (GMutex * mutex);
म्यूटेक्स अनलॉक:
शून्य g_mutex_unlock (GMutex * mutex);
म्यूटेक्स को लॉक करने का प्रयास करें:
gboolean g_mutex_trylock (GMutex * mutex);
यदि म्यूटेक्स मुक्त है, तो यह अवरुद्ध है और फ़ंक्शन TRUE देता है, अन्यथा फ़ंक्शन तुरंत बाहर निकलता है और FALSE को वापस करता है।
म्यूटेक्स हटाना:
शून्य g_mutex_free (GMutex * mutex);
एक उदाहरण जिसमें साझा करने से सुरक्षित कोड के साथ महत्वपूर्ण_फंच () फ़ंक्शन को मुख्य और अतिरिक्त धाराओं से एक साथ कहा जा सकता है:
void critical_func(GMutex *mutex)
{
g_mutex_lock (mutex);
// -
...
g_mutex_unlock (mutex);
}
// ;
gpointer thread_func(gpointer data)
{
GMutex *mutex = (GMutex*)data;
critical_func(mutex);
return 0;
}
int main (int argc, char *argv[])
{
GMutex *mutex = g_mutex_new();
//
GThread *thread_id = g_thread_create(thread_func,mutex,TRUE,NULL);
critical_func(mutex);
//
g_thread_join(thread_id);
return 0;
}
ध्यान दें: पहले से ही बंद म्यूटेक्स के अंदर g_mutex_lock () को याद करने से प्रोग्राम ब्लॉक नहीं होगा और इसे केवल अनदेखा किया जाएगा, जो बार-बार लॉक होने से बचाता है।
शर्त
शर्त के रूप में अनुवाद किया जाता है, लेकिन
सिग्नल शब्द मामले की तकनीक के लिए अधिक उपयुक्त है। यह विंडोज इवेंट्स का एक एनालॉग है, लेकिन पूरा नहीं: यदि किसी सिग्नल को पहले की अपेक्षा भेजा गया था, तो यह शून्य में चला जाएगा और इसके लिए इंतजार करना बेकार होगा। इसलिए, इवेंट रीसेट की कोई अवधारणा नहीं है, जैसा कि विंडोज में है।
सिग्नल निर्माण (स्थितियां):
GCond * g_cond_new (शून्य);
एक संकेत भेजें:
शून्य g_cond_signal (GCond * cond);
सिग्नल के लिए अंतहीन प्रतीक्षा करें:
शून्य g_cond_wait (GCond * cond, GMutex * mutex);
दिए गए समय से अधिक सिग्नल के लिए प्रतीक्षा करें:
gboolean g_cond_timed_wait (GCond * cond, GMutex * mutex, GTimeVal * abs_time);
उदाहरण
उदाहरण एक संकेत के उपयोग को प्रदर्शित करता है कि एक स्ट्रीम के शुरू होने के बाद प्रतीक्षा करें।
GMutex *mutex = NULL;
GCond *cond = NULL;
// ;
gpointer thread_func(gpointer data)
{
//
// ...
//
g_mutex_lock (mutex);
g_cond_signal(cond);
g_mutex_unlock(mutex);//
// ...
return 0;
}
//
int main (int argc, char *argv[])
{
GTimeVal timeval;
gboolean return_val;
//
g_thread_init(NULL);
// ()
mutex = g_mutex_new();
cond = g_cond_new();
// ,
g_mutex_lock(mutex);
//
g_thread_create( thread_func,NULL,TRUE,NULL);
//
g_get_current_time(&timeval);//
g_time_val_add(&timeval,G_USEC_PER_SEC);//
//
return_val = g_cond_timed_wait(cond,mutex,&timeval);// mutex ,
if(!return_val)
printf(" \n");
g_mutex_unlock(mutex);
return 0;
}
नोट: सिग्नल की प्रतीक्षा करना बंद म्यूटेक्स के अंदर होना चाहिए, और लॉक म्यूटेक्स के अंदर सिग्नल भेजने की भी सिफारिश की जाती है, हालांकि यह आवश्यक नहीं है।
प्रतीक्षा करते समय, म्यूटेक्स को अस्थायी रूप से अनलॉक किया जाता है ताकि आप दूसरे धागे से उसी म्यूटेक्स के अंदर जा सकें और एक संकेत भेज सकें।
ग्लिब कहां से लाएं
linux:
प्रत्येक लिनक्स वितरण में एक glib है, आप इसे निम्नानुसार सत्यापित कर सकते हैं:
pkg-config - cflags glib-2.0
विंडोज:
कई dll पुस्तकालयों की आवश्यकता है: libgthread-2.0-0.dll, libglib-2.0-0.dll और intl.dll।
ग्लिब 2.28.8 के लिए, ये फाइलें 1.4 एमबी पर कब्जा करती हैं (संग्रह में 2 गुना कम)
मूल प्रलेखन के साथ और अनावश्यक स्थानीयकरण फ़ाइलों के बिना एक तैयार पुस्तकालय
यहां पाया जा सकता
है ।
Glib का नवीनतम पूर्ण संस्करण हमेशा इस लिंक पर डाउनलोड किया जा सकता है:
http://ftp.acc.umu.se/pub/gnome/binaries/win32/glibइस स्थिति में, आपको यहां से ली गई intl.dll फ़ाइल की भी आवश्यकता होगी:
http://ftp.acc.umu.se/pub/gnome/binaries/win32/dependencies/gettext-runtime_0.18.1.1-2_win32.zipवैसे, लाइब्रेरी का 64-बिट संस्करण है:
http://ftp.acc.umu.se/pub/gnome/binaries/win64/glibMacOS:
मुझे नहीं पता कि वास्तव में मैकओएस पर चीजें कैसी हैं, लेकिन ग्लिब भी है।
परियोजना के लिए कनेक्शन
ग्लिब लाइब्रेरी एक एच-फाइल के साथ जुड़ा हुआ है:
# अलग करना <glib.h>
लिनक्स और mingw32:
H-files के लिए मार्ग खोजें:
pkg-config -cflags gthread-2.0
जुड़े हुए पुस्तकालयों का पता लगाएं:
pkg-config --libs gthread-2.0
उदाहरण मेकफाइल:
CC=gcc
DEBUG = -g3
RELEASE = -o3
FLAGS := $(shell pkg-config --cflags gthread-2.0)
LIBS := $(shell pkg-config --libs gthread-2.0)
SOURCES= test_app.c
test_app : $(SOURCES)
$(CC) -o $@ $(SOURCES) $(DEBUG) $(FLAGS) $(LIBS)
all : test_app
clean:
rm -f *.o
विंडोज:
प्रोजेक्ट में वह पथ लिखें जहाँ h-files हैं:
शामिल / glib-2.0
lib / glib-2.0 / शामिल हैं
परियोजना के लिए दो कामगार फाइलें कनेक्ट करें:
gthread-2.0.lib
GLib-2.0.lib।
GTK अनुप्रयोग सुविधाएँ
बहु-थ्रेडेड Gtk एप्लिकेशन में, एक साथ कई थ्रेड्स से Gtk या Gdk फ़ंक्शन को एक्सेस करने से अप्रत्याशित परिणाम हो सकते हैं, आमतौर पर ग्राफिक्स विरूपण या एप्लिकेशन फ्रीज होते हैं।
इस अप्रिय स्थिति के आसपास जाने के लिए, आपको सभी थ्रेड्स में कोड को एक विशेष महत्वपूर्ण अनुभाग के अंदर Gtk और Gdk फ़ंक्शन के साथ कॉल करने की आवश्यकता है, अर्थात। निम्नलिखित कार्यों के लिए कोड को प्रतिबंधित करें:
// महत्वपूर्ण अनुभाग दर्ज करें
gdk_threads_enter ();
// महत्वपूर्ण अनुभाग से बाहर निकलें
gdk_threads_leave ();
उपयोग उदाहरण:
// ;
gpointer thread_func(gpointer data)
{
//
gdk_threads_enter();
gtk_label_set_text(label," ");
//
gdk_threads_leave();
return 0;
}
int main (int argc, char *argv[])
{
GtkWidget *window;
//
if(!g_thread_supported())
{
g_thread_init(NULL);
// gdk_threads_enter() gdk_threads_leave()
gdk_threads_init();
}
//
gdk_threads_enter ();
gtk_init (&argc, &argv);
// ;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
//
// ...
//
g_thread_create(thread_func,NULL,FALSE,NULL);
gtk_main();
//
gdk_threads_leave ();
return 0;
}
मुझे खुशी होगी अगर किसी ने लेख को उपयोगी पाया।