اتصال غير متزامن ويتفوريكسيت
هذا السؤال لديه بالفعل جواب هنا: أنا بحاجة إلى تفرخ عملية الطفل الذي هو تطبيق وحدة التحكم، والتقاط انتاجها. لقد كتبت التعليمات البرمجية التالية لطريقة: ومع ذلك، هذا لا يعود أي شيء. لا أعتقد أن يتم استدعاء الحدث أوتبوتداتاريسيفد مرة أخرى، أو الأمر ويتفوريكسيت () قد حظر مؤشر الترابط بحيث لن رد. إديت: يبدو أني كنت أحاول جهدا صعبا مع رد الاتصال. القيام: يظهر للعمل بشكل جيد. طلب 12 نوفمبر 08 في 23:14 ملحوظ كنسخ من قبل لو فنه Ph250c. كزة c يمكن للمستخدمين الذين لديهم شارة c أن يقوموا بإغلاق الأسئلة منفردة على شكل نسخ مكررة وإعادة فتحها حسب الحاجة. 17 أكتوبر في 10:58 وقد تم طرح هذا السؤال من قبل ولها بالفعل جواب. إذا كانت هذه الإجابات لا تعالج سؤالك بشكل كامل، فيرجى طرح سؤال جديد. إذا كنت aren39t الذهاب إلى التفاعل مع التطبيق والعناية فقط عن انتاجها، يجب أن لا تستخدم أسينك بيجينوتبترادلين () وبدء () طريقة للقيام بذلك. لقد وجدت هذه لتكون غير موثوقة للغاية، وأنها يمكن في بعض الأحيان اقتطاع بداية الانتاج application39s. نداش مايكل غراتشيك 16 16 في 23:47 Isn39t أن حالة توقف تام في انتظار يحدث مسن محرر يقول أنك خطر الجمود إذا الاستماع إلى كل من الإخراج والخطأ في نفس الوقت. سوف تتوقف التطبيق إذا المخزن المؤقت الخطأ هو الكامل، والانتظار حتى لتفريغ. ولكن you39re لا تفريغ المخزن المؤقت الخطأ حتى يتم الانتهاء من المخزن المؤقت الإخراج (الذي فاز 39t يكون التطبيق ينتظر المخزن المؤقت الخطأ). نداش مايكل بيسبجيرغ 31 مارس 13 في 15:42 الجواب من يهوذا لا يعمل بالنسبة لي (أو لم يكتمل) كما كان التطبيق الخروج بعد بيجينوتبترادلين الأول () هذا يعمل بالنسبة لي كمقتطف كامل، وقراءة الانتاج المستمر من بينغ: إدخال أنابيب جوستين فان باتن يتضمن أوركاس أكتوبر تقنية المجتمع معاينة (كتب) أنواع جديدة التي تجعل من السهل للمطورين لاستخدام أنابيب من التعليمات البرمجية المدارة. وتستخدم الأنابيب للاتصال بين العمليات (إيبك) بين العمليات التي تعمل على نفس الجهاز، أو العمليات التي تعمل على أي جهاز آخر ويندوز داخل الشبكة. وأضاف W8217ve الدعم لكل من الأنابيب المجهول واسمه. أنواع الأنابيب الجديدة يمكن العثور عليها في System. Core. dll ضمن مساحة الاسم System. IO. لاحظ أنه بعد أن خرج كتب كتب أكتوبر، انتقلنا أنواع الأنابيب من System. IO إلى System. IO. Pipes، وبالتالي فإن الأنواع ستكون في مساحة الاسم الجديدة في كل كتبس المستقبلية. أنابيب مجهولة المصدر أنابيب مجهولة الهوية تستند إلى حرف وهي نصف المزدوجة. لا يمكن الاتصال عبر الشبكة ودعم مثيل خادم واحد فقط. هذه الأنابيب هي الأكثر فائدة للاتصال بين المواضيع أو بين العمليات الأم والطفل حيث يمكن التعامل مع مقابض الأنابيب بسهولة عند إنشاء عملية الطفل. مثال 1: أنابيب مجهولة يوضح المثال التالي إرسال سلسلة من عملية رئيسية إلى عملية فرعية. يتم قراءة خط من وحدة التحكم الأم وإرسالها إلى عملية الطفل. عملية الطفل ثم يكتب السلسلة التي تلقتها من العملية الأصل إلى وحدة التحكم. عملية معالجة عملية جديدة () باستخدام (أنونيموسبيبسرفرستريم بايبريم جديد أنونيموسبيبسرفرستريم (بايبديركتيون. أوت، هاندلينهريتابيليتي. Inheritable)) أنابيب مجهولة الحلو صدى: أنابيب مجهول الحلو اسمه أنابيب أنابيب اسمه هي أقوى بكثير من الأنابيب المجهولة. ويمكن أن تكون مزدوجة، عبر الشبكة، ويمكن أن تدعم مثيلات خادم متعددة من اسم واحد، مما يجعلها مثالية لسريع لبناء، وسهلة للاتصال، وخوادم متعددة مؤشرات. وعلاوة على ذلك، فإنها تدعم الاتصالات القائمة على رسالة بحيث عملية القراءة يمكن قراءة رسائل مختلفة طول بدقة كما أرسلت من قبل عملية الكتابة. وأخيرا، تدعم الأنابيب المسماة انتحال الهوية مما يسمح بربط العمليات باستخدام مجموعة الأذونات الخاصة بها على الخوادم البعيدة. المثال 2: الأنابيب المسماة في الحالات التي لا يمكن فيها أن ترث العملية الثانية مقبض الأنبوب، يمكن استخدام الأنابيب المسماة. يوضح المثال التالي إرسال سلاسل من عملية العميل إلى عملية الملقم. باستخدام (نامدبيبسرفرستريم بيبستريم جديد نامدبيبسرفرستريم (8220testpipe8221)) باستخدام (سترمريدر سر ستريمريدر جديدة (بيبستريم)) بينما ((تيمب sr. ReadLine ()) نول) وحدة التحكم. WriteLine (8220: 8221. داتيتيم. Now، تيمب) باستخدام (نامدبيبكلينتستريم بايبريم نامدبيبكلينتستريم (8220testpipe8221)) باستخدام (ستريموريتر سو ستريموريتر جديد (بيبستريم)) بينما ((وحدة التحكم تيمب. ReadLine ()) نول) مثال 3: أنابيب اسمه مع الرسائل المسماة أنابيب أيضا دعم الاتصالات القائمة على الرسالة. وهذا يسمح لعملية القراءة لقراءة رسائل طول مختلفة على وجه التحديد كما أرسلت من قبل عملية الكتابة. يعرض المثال التالي كيفية إرسال هذه الرسائل وقراءتها. UTF8 ترميز جديد UTF8Encoding () سترينغ message1 8220Name بايب مساج Example.8221 سترينغ message2 8220Another نامد بايب مساج example.8221 باستخدام (نامدبيبسرفرستريم بايبستريم جديد نامدبيبسرفرستريم (8220messagepipe8221.PypeDirection. InOut، 1، بيبترانزميسيونمود. Message، بيبوبتيونس. None)) // ليترسكوس إرسال رسالتين. (0)، بايت ستريم (بايت، 0، bytes. Length) بواسطة براد كوكس مؤسسة ستيبستون 75 غلين رود ساندي هوك، كت 06482 203 426 1875 تاسكماستر، أوبجكتيف-C، إيكباك، و سوفتوار-إيك هي علامات تجارية لشركة ستيبستون كوربوراتيون. مقدمة (توك) تاسكماستر يدعم واحدة من عدة طبقات في بنية متعددة المستويات المنحى الكائن الذي ستيبستون وقد تم بناء بطريقة أسفل إلى أعلى منذ إنشائها. وستصف هذه الوثيقة أنواع الأنظمة القابلة للبرمجة التي نتصورها، وهي بنية برمجيات متعددة المستويات لبناءها، والدور الذي تلعبه تاسكماستر ضمن هذه البنية، وكيفية ارتباط تاسكماستر بالطبقات المجاورة، مثل C ونظام تشغيل المنصات. تاسكماستر هي مكتبة من الوظائف القائمة على C التي تدعم خفيفة الوزن متعددة المهام والتعامل مع استثناء بحيث تطبيقات العميل المحمولة عبر الأجهزة / منصات البرمجيات. عن طريق المحمولة، ونحن نعني أن تطبيقات العميل الوصول إلى ميزات تاسكماسترز من خلال واجهة برنامج التطبيق (أبي) التي هي منصة مستقلة. ويدعم هذا أبي طبقة من التعليمات البرمجية المعتمدة منصة (بدل) التي تتكيف أبي إلى الأجهزة والبرامج المضيف (نظام التشغيل). للمنصات التي تدعم بالفعل بعض قدرات تاسكماسترز (ماخ، أوس / 2)، يستخدم بدل قدرات منصات. بالنسبة للمنصات التي تفتقر إلى هذه الميزات (أونيكس، مس / دوس)، فإن بدل يزودها بالتلاعب المباشر بالأجهزة (سجلات الماكينة) التي تكمن وراء بيئة تشغيل وقت التشغيل C. لمنصات صن يونكس، والتي هي حاليا المنصة الوحيدة التي تم استدعاؤها تاسماستر، وكتب بدل في C مع واحد صغير (8 بيان) الروتين الفرعي في المجمع. استفسارات العملاء هي موضع ترحيب بشأن تاسكماستر، سواء على منصة الشمس الحالية أو استدار لمنصات إضافية. الاتصال ب K. K. تان في 203 426 1875. نظم برمجة المستخدم (توك) الأوراق المصاحبة، تخطيط الثورة الصناعية البرمجيات وهناك رصاصة فضية 2 تصف الرؤية بعيدة المدى وراء هذا العمل. ويرون أن أزمة البرمجيات تمثل عقبة أمام الانتقال من عصر التصنيع إلى عصر المعلومات، حيث أصبحت الحواسيب مركبة شخصية لكل شخص في شبكة معلومات عالمية، وهي النموذج T فورد في عصر المعلومات. وهم يرون أزمة البرمجيات كما يجري حلها كما تم حل نقص مشغل الهاتف مرة واحدة، من خلال جعل كل مستخدم الكمبيوتر مبرمج. وبطبيعة الحال، فإن مبرمج لا يعني ما يفعله اليوم. وستكتسب الكلمة العديد من المعاني المختلفة المناسبة لمهارات ومصالح فئات متنوعة من المستخدمين على مستويات مختلفة من بنية برمجيات متعددة المستويات. على سبيل المثال، توم، ديك، وهاري هي المبرمجين نموذجية مع مهارات واهتمامات مختلفة تماما: توم هو مبرمج في C الشعور هذه الكلمة. توم يلعب الدور الذي تلعبه شركات تصنيع السيليكون في الأجهزة، وصناعة مكونات السيليكون على مستوى البوابة والكتلة إلى مكونات على مستوى رقاقة يمكن للآخرين ذوي المهارات الأقل تخصصا، مثل ديك، استخدامها. إن تقنيات البوابة والكتلة، سواء في الأجهزة أو البرامج، هي أنشطة مقترنة بإحكام، حيث يكون تحسين المنتج، وليس المطور، أمرا بالغ الأهمية. ديك هو مبرمج في سمالتالك أو الهدف - C الشعور كلمة. يلعب ديك الدور الذي يلعبه بائعي البورد في الأجهزة، ويجمعون مكونات رقاقة المستوى التي ينتجها توم إلى مكونات على مستوى بطاقة يمكن للآخرين ذوي المهارات الأقل تخصصا، مثل هاري، استخدامها. إن التكنولوجيات على مستوى رقاقة، سواء في الأجهزة أو البرامج، هي أنشطة مقترنة بشكل فضفاض، حيث تكون اهتمامات المطورين مثل القابلية للتوصيل والتبادل وإعادة الاستخدام أمرا بالغ الأهمية. تدعم التقنيات على مستوى رقاقة هذا الترسيم الحاسم بين تقنيات التصنيع المتشابكة بإحكام والتي يستخدمها المتخصصون ذوي المهارات العالية فقط، مثل المسابك السيليكونية، وتقنيات التجميع الأكثر بساطة والأكثر ارتباطا والتي يمكن لغير المتخصصين استخدامها، مثل المفكات ومكابس اللحام. هاري هو المستخدم النهائي، واحدة من بقية منا. هاري هو خبير في مجال المشكلة مع عدم وجود خبرة برامج متخصصة على الإطلاق. والهدف من الهندسة المعمارية التي سيتم مناقشتها في هذه الورقة هو جعل هاري مبرمج على مستوى بطاقة في وجه التحديد أن محدود ولكن مع ذلك شعور حقيقي أن المستخدمين النهائيين هم على مستوى بطاقة مصممي الأجهزة عندما يختارون البطاقات التي سوف تشتري لتخصيص شخصية الحاسوب. قد يكون هاري كاتب في مكتب التأمين، أو مدير مكتب فرع البنك، أو في المثال التالي، صاحب منزل يستخدم حاسوب شخصي لإدارة الشؤون المالية للأسر. اليوم، قد يستخدم هاري برنامج التمويل الشخصي الجاهز مثل ماناجيمنتورموني (ميم) على نظام ماكنتوش. هذه البرامج تسمح هاري إدارة أصوله، والخصوم، والدخل، والنفقات لتوفير القراءة الفورية من صافي القيمة الشخصية. ما هي برامج وأنظمة اليوم لا تفعله هو مساعدة هذه الفئة من المستخدمين على بناء حلول مخصصة خاصة بهم لاحتياجاتهم الخاصة بالمشكلات. لا يدعم نظام التشغيل ماسينتوش برمجة المستخدم النهائي. على سبيل المثال، لنفترض أن بعض أصول هاريس موجودة في الأسهم والسندات والصناديق المشتركة، والتي تتفاوت مساهمتها في صافي القيمة يوميا. عندما الإطارات هاري من كتابة أسعار الأسهم من الصحيفة انه قد تغامر في عصر المعلومات من خلال برمجة المحاكي محطة للحصول على معلومات الأسعار من خدمة المعلومات مثل كومبوسيرف إلكترونيا. على الرغم من أن هاري من المرجح أن برنامج من أي وقت مضى في C أو حتى سمالتالك، وقال انه قد تصل جيدا إلى نقطة استخدام جدول بيانات مثل إكسيل لإدارة قاعدة بيانات لاتجاهات الأسعار مع مرور الوقت، وربما باستخدام إكسيلز مرافق الرسم البياني لإظهار الاتجاهات بيانيا. والحلول غير القابلة للبرمجة اليوم كافية إلا إذا بقيت هاري مقتنعة بأن كل هذا التحرك حول 3 لفتح وإغلاق الوثائق وبدء ووقف التطبيقات، وقطع ولصق الأرقام هو تحسن كبير على كتابة كل رقم يدويا إذا هاري يجب أن تصر على طريقة لبناء تطبيقه الخاص لحساب، بنقرة واحدة، رسم بياني من صافي قيمته الشخصية كما يتغير مع مرور الوقت، رغباته قد تجاوز ما ماسينتوش على وجه الخصوص، وصناعة البرمجيات ككل، يمكن أن تقدم اليوم. ويوضح الشكل 1 الحل المتوخى في هذه الوثيقة. الشكل 1: برنامج يمكن أن ينشئه مستخدم نهائي، مكتوب بلغة برمجة إجرائية غير إجرائية على مستوى بطاقة إجرائية من النوع المتوخى في هذه الوثيقة. ويتكون هذا الرقم من رموز ماكنتوش ومكبات الشاشة للدلالة على أن كل رمز يتصرف بشكل فردي كما هو الحال في ماكنتوش اليوم. ومع ذلك هناك اختلافات كبيرة. الصورة ليست مجموعة من ما كنت ترى، هو كل شيء يمكنك الحصول على الرموز التي يمكن استخدامها فقط يدويا، و (باستثناء قطع اليد واللصق) بشكل فردي. هذا الرقم هو مصدر قائمة للبرنامج الذي كتبه هاري في لغة البرمجة الكائن الموجهة على مستوى بطاقة مبدع، والتي تستند الكائنات على مرافق متعددة المهام خفيفة الوزن من هذه الورقة. تمثل الرموز مهام خفيفة الوزن أو كائنات على مستوى البطاقة. هاري قد ينقذ برنامجه حساب نت وورث كمكون جديد على مستوى بطاقة واستخدامها جنبا إلى جنب مع تلك المعروضة هنا. ومع ذلك هاري لم بناء تلك التي تظهر في هذا الرقم. قام بشراءها في مكان آخر، من ديك، الذي جمعها من مكونات على مستوى رقاقة ملفقة من قبل توم. المهام هي في البداية غير نشطة، كل في انتظار المدخلات على الأسهم الواردة. عندما يتم النقر على زر حساب صافي القيمة (على شاشة أخرى غير موضح هنا)، وهذا ينتج إشارة أن رمز المحاكي الطرفية ينتظر. يؤدي هذا إلى تشغيل عنصر التحكم في رمز المحاكي الطرفية، والذي قد يكون تجسيدا على مستوى بطاقة برنامج مثل سمارتكومي، لطلب الهاتف، وتسجيل الدخول إلى كومبوسيرف، واكتب الأوامر لتنزيل المعلومات المالية. رموز البحث سلسلة ثلاثة هي طريقة هاريس للتعامل مع حقيقة أن كومبوسيرف لا توفر المعلومات المالية في شكل أن جدول بياناته يمكن أن تقبل. وقد استخدم عملية تقسيم الفاصل (الدائرة السوداء الصغيرة) لإرسال البيانات إلى ثلاث عمليات بحث عن سلسلة، وقد برمجت هذه للعثور على أسعار الأسهم المحددة وتنسيقها كما تتوقع جداول البيانات الثلاثة. وهكذا دواليك. والمبرمجين يونكس التعرف على هذا باعتباره الاختلاف على الأنابيب والمرشحات مخطط يونيكس. ولكن هناك فرق كبير واحد أن بلدي استخدام برامج ماكنتوش مألوفة لا يبرز بوضوح. على عكس أنابيب يونيكس التي يمكن أن تحمل فقط تيارات من بايت، يمكن للسهام في هذا الشكل تحمل تيارات من الكائنات على مستوى رقاقة. على عكس جداول بيانات ماسينتوش التي تقبل النص فقط، يتم كتابة البرامج في هذا الشكل لقبول البيانات التي تعبر عنها كائنات. يمكن أن تمثل الكائنات أي نوع منظم من البيانات، بما في ذلك الهياكل القائمة على المؤشر مثل القوائم والأشجار. يجب ألا يكون السهم الذي يمثل دفق الإدخال إلى رمز ورقة الانتشار سلاسل محددة بعلامات جدولة بحيث يجب تحليل جدول البيانات وإعادة تهيئته داخليا. يمكن للسهم إلى كائن جدول البيانات أن يحمل مجموعة من الكائنات. حالات سجل الدرجة، وليس تيار حرف محدد بعلامات جدولة كما تتطلب جداول البيانات اليوم. هندسة البرمجيات متعددة المستويات (توك) سوف تستخدم هذه الوثيقة هذا المألوف ولكن غير مفهومة جيدا الكلمة الطنانة، وجوه، مع دقة من معنى معنى هذه الكلمة في الأجهزة. أي أن الكائن لن يحمل أي معنى تقني مهما كان، إلا إذا كان مؤهلا لجعل السياق المعماري واضح. كما أن كائن الأجهزة على مستوى البوابة ليس له شيء مشترك مع كائن الأجهزة رقاقة، أو بطاقة، أو الرف، لذلك سيكون مع كائنات البرامج المتنوعة في بنية البرمجيات متعددة المستويات. وقد كان الدافع وراء هذا العمارة من خلال التقدير للمعماريات متعددة المستويات للهندسة الأجهزة، حيث يتم بناء الأجسام عالية المستوى الأجهزة مثل المعدات المكتبية من الأجسام ذات المستوى الأدنى مثل البطاقات، والكائنات على مستوى بطاقة من الأجسام ذات المستوى المنخفض مثل رقائق السيليكون، و والأجسام على مستوى رقاقة من الكائنات على مستوى أدنى مثل كتل السيليكون والبوابات. ويتوقع أن يتطور حل الأزمة البرمجية كما حدث في الأجهزة، من خلال تصنيف المستخدمين / المبرمجين وفقا لمستويات ومهارات المهارة، تماما كما يتم تقسيم سوق إمدادات السباكة إلى أصحاب المنازل والسباكة ومنافذ البيع بالتجزئة والمصانع ومصافي النفط و الألغام. سوف يستخدم المستخدمون النهائيون، مثل هاري، تقنيات نمطية / ملزمة مبسطة كافية لفئات محدودة من المشاكل، مثل كائنات مستوى البطاقة الموصوفة هنا. وسيحصلون على الأشياء اللازمة من خلال التعاقد من الباطن على العمل مع عمال أقل تخصصا مثل توم أند ديك. ويبين الشكل 2 المستويات الخمسة لهذا الهيكل. على الرغم من أن الكائنات في كل مستوى تفي بالتعريف الكلاسيكي للأجسام باعتبارها وحدات لا يمكن فصلها عن الدولة والسلوك، فإن الآليات النمطية / ملزمة التي يتم إنجازها هي متنوعة تماما على مستويات مختلفة: البوابة ومستوى كتلة الكائنات هي التعبير - و كائنات على مستوى روتيني من لغات البرمجة التقليدية مثل كوبول، باسكال، و C واللغات ذات وجوه مقترنة بإحكام مثل أدا و C. مع وحدات على مستوى البوابة (التعبيرات، وحدات الماكرو، وما إلى ذلك)، يتم الربط بين الكائنات تماما في وقت تجميع من قبل مترجم. كتلة مستوى وحدات (مكتبات روتين)، والتأخير ملزمة حتى وقت الارتباط، حيث يحدث العمل في رابط. الأجسام على مستوى رقاقة هي فضفاضة إلى جانب، ملزمة حيوي، الكائنات كما ظهرت في لغات مثل سمالتالك والهدف - C. مع نمطية على مستوى رقاقة، يتم تأجيل الربط حتى آخر لحظة ممكنة. يتم التجليد من قبل البرنامج نفسه في مصلحة اقتران فضفاض، وإعادة الاستخدام، والتبادل، وقابلية التوصيل. جميع الطبقات اللاحقة تشترك في هذه الخاصية من الارتباط المتأخر، على الرغم من استخدام مجموعة متنوعة من الوسائل لتحقيق ذلك. ويبين الشكل أن C، على عكس أدا، يوفر دعما محدودا للبرمجة على مستوى رقاقة في آلية وظيفتها الافتراضية، وهو شكل من أشكال ديناميكية ملزمة. دعم كس لاقتران فضفاض محدودة من خلال التركيز على اقتران ضيق، والميراث القائم على تجميع الوقت نوع فحص وربط ثابت. الكائنات على مستوى البطاقة هي كائنات على مستوى المهمة من أنظمة متعددة المهام خفيفة الوزن مثل فابريك، مجاز، و الرئيس المتعسف. وسوف يكون التركيز الرئيسي لهذه الورقة. وتمدد وحدات نمطية على مستوى البطاقة المعنى التقليدي للتغليف لتزويد كل كائن بخيوطه الخاصة من التحكم وساعة الساعة الداخلية والشعور بالتاريخ بالإضافة إلى الأشياء ذات المستوى الأدنى والتي تحافظ على حالتها وسلوكها ولكن ليس تاريخها . الأجسام على مستوى الرف هي وحدة نمطية الأقدم والأكثر إحكاما المغلفة من كل شيء، والمفهوم المألوف من برنامج وحدة مستقلة بشكل مستقل من الوظائف التي نختار بين عند شراء البرمجيات في مخزن البرامج المحلية أو عند اختيار ما البرنامج لتشغيل على نظام كمبيوتر شخصي أو مشترك. الشكل 2: المنحى الكائن يعني أشياء مختلفة على مستويات مختلفة من التكامل. شرائح الفطيرة تمثل مدى دعم العديد من اللغات الشعبية العمل على كل مستوى. كما هو الحال في الأجهزة، ما يميز نمطية على مستوى رقاقة من وحدات مستوى كتلة أو كتلة هو اقتران فضفاض، ملزمة ديناميكية، أو القابلية للتوصيل. وفي حين أن تكنولوجيات البوابة والكتل هي تقنيات التصنيع التي تقوم بتصنيع الأشياء من المبادئ الأولى، فإن تقنيات الرقائق والمستويات الأعلى هي تقنيات التجميع لتجميع الأشياء عن طريق توصيل المكونات الجاهزة من مكتبات الأجزاء الجاهزة للاستخدام. ولا یوجد أي من ھذه المستویات دواء شفاف یلغي الحاجة إلی مستویات أخرى. على نطاق أي نظام كبير، البوابة، كتلة، وحتى على مستوى رقاقة الكائنات هي وحدات صغيرة للغاية من تحبب - الحبوب من الرمل حيث هناك حاجة الطوب. ولكن نمطية مستوى الرف من أنظمة التشغيل مثل ماسينتوش و أونيكس تذهب بعيدا جدا في الاتجاه المعاكس. والتغليف الدقيق الذي يجعل نمطية مستوى الرف مفيدة جدا لحزم برامج التعبئة والتغليف كبرامج مستقلة، ويعوق التبادل الحر للمعلومات بين هذه الأجسام بدقة شديدة بحيث لا يمكن برمجة المستخدمين النهائيين. وحدة نمطية على مستوى بطاقة يوفر وسطا، وسيطة بين كائنات على مستوى رف مغلفة بإحكام من أنظمة التشغيل مثل يونيكس والكائنات على مستوى رقاقة من لغات البرمجة مثل سمالتالك. مثال: فابريك و سمالتالك (توك) تعتبر العلاقة بين Fabrik4 و سمالتالك مثالا ممتازا لكيفية ارتباط الكائنات على مستوى البطاقة بأجسام المستوى الأدنى. وقد كتب فابريك في سمالتالك، لذلك يتكون داخليا من الأشياء على مستوى رقاقة. المبرمجين سمالتالك التلاعب بها عن طريق لغة البرمجة سمالتالك واجهة المستخدم كائن المنحى النص المناسب لأخصائيي البرمجيات مثل ديك. فابريك مشروع نوع أعلى مستوى من الكائن على واجهة المستخدم كائن على مستوى بطاقة. غير المبرمجين التلاعب هذه عبر فابريكس واجهة المستخدم مبدع، وهي لغة البرمجة غير النصية مناسبة لغير المتخصصين مثل هاري. من وجهة نظر هاريس، هذه الكائنات الجديدة جذابة حدسي لأنها قابلة للتفكير مهارات الحياة اليومية. فهي تواصل، وليس بشكل متزامن من خلال الاحتجاج الإجرائي (وهو أمر يجده المبرمجون فقط طبيعيا)، ولكن من خلال نموذج غير متزامن يكون أكثر ارتباطا بكيفية تصرف الأشياء المألوفة من التجربة اليومية. تقوم كائنات مستوى البطاقة بتغليف نسخة من سلسلة أدوات التحكم على بطاقة برامج، إلى جانب العناصر على مستوى رقاقة المستخدمة لبناء تلك البطاقة. وهي كائنات من النوع الذي يدعو المبرمجين العمليات خفيفة الوزن الكائنات التي تعمل كروتينات من بعضها البعض، وليس الفرعية. ويتواصلون بشكل غير متزامن عن طريق إرسال كائنات على مستوى رقاقة من خلال كائنات قنوات الاتصالات مثل الجداول. وبما أن بطاقات البرامج تظهر في وقت واحد، فإن واجهة المستخدم الخاصة بها هي بديهية فريدة. لهذا السبب وحده، فهي أكثر جذرية وجوهية من اللغات الإجرائية، وحيدة الخيوط من اليوم. مثل الأشياء الملموسة من التجربة اليومية، كائنات على مستوى بطاقة توفر موضوع الخاصة بهم من السيطرة داخليا، فإنها لا التواصل عن طريق الإجرائية الإجرائية، فإنها لا تدعم الميراث، واجهة المستخدم الخاصة بهم هو مبدع، وليس النص. كائنات على مستوى بطاقة تشبه أنابيب يونكس والمرشحات أنها تشترك في نفس المفهوم غير الإجرائي من العمليات المتزامنة التواصل من خلال كائنات قناة الاتصالات غير متزامن، أو الأنابيب. أنها تختلف في تلك الكائنات على مستوى بطاقة هي عمليات خفيفة الوزن. وهم يتشاركون في مساحة عنوان مشتركة، وبالتالي لا يقتصر على التواصل تيارات القيمة، أو بايت. ويمكن أن تكون الجداول بينها تيارات مرجعية قد تحتوي على مؤشرات مدمجة مثل القوائم أو الأشجار المرتبطة. في حين أن الأنابيب تحمل فقط بايت، يمكن أن تيارات تحمل الكائنات. مثال: المجاز (توك) ميتافور 5 هو مثال ذي صلة مع وجود اختلافات كبيرة. فابريك و ميتافور متشابهة في كل من دعم لغة برمجة مبدعة موجهة نحو غير المبرمجين. ويستند كلاهما على فقاعات غير الإجرائية والسهام برمجة نموذج مثل أنابيب يونكس والفلاتر نموذج. كلاهما يختلف عن يونكس في أن الفقاعات يمكن تبادل تيارات المرجعية (الهياكل القائمة على مؤشر) مثل الكائنات، وليس فقط تيارات القيمة كما هو الحال مع أنابيب يونكس. الفرق الكبير هو عدم وجود العمارة المفتوحة التي يكتسبها فابريك من كونه يستند إلى معيار مفتوح مثل سمالتالك. أفهم، استنادا إلى معلومات قد تكون معيبة 6. أن المجاز هو الآن، أو كان في الأصل، على أساس الملكية الملكية ونظام التشغيل الملكية. وهذا يعني عدم وجود معيار مفتوح للمستوى المعماري المقابل لأونيكس (التكامل على مستوى الرف). وبما أن الاستعارة قد تم تطويرها قبل أن تصبح لغات البرمجة ذات التوجه الكائن شائعة، فلا يوجد شيء، بصرف النظر عن معايير الترميز الداخلية، لدعم دور مستوى الرقاقة الذي تلعبه الكائنات الصغيرة في فابريك. إذا كانت الشائعات المستمرة صحيحة أن بعض أو كل الكائنات المستعارة على مستوى بطاقة تم ترميزها في المجمع، حتى المعايير المفتوحة على مستوى البوابة والكتلة التي المبرمجين C تأخذ على النحو الممنوح (الروتين والعبارات) إما مفقودة تماما، أو أكثر من المعقول، لا توفر إلا بمعايير داخلية مغلقة. أنا أفهم أن معايير الترميز الداخلية موجودة حيث يتم إرسال الكائنات على مستوى بطاقة ميتافورس من خلال تمثيل جدولي موجه نحو بيانات جدول البيانات. وأنا أفهم أن المجاز ينظر الآن إلى هذا التمثيل باعتباره عقبة أمام النمو المستمر، ويفترض أن ذلك بسبب صعوبة إجبار البيانات غير الجدولية التي يتكرر أحيانا في تطبيقات العملاء لتتناسب مع نموذج البيانات مجاز جدولي. وأنا أفهم أن تخفيف هذه العوائق وغيرها من الحواجز، مثل عدم قابلية النقل، هو الدافع وراء المشروع المشترك المجازي / عب مؤخرا باتريوت بارتنرز. النهج متعدد الطبقات المدعو في هذه الوثيقة يعالج المشاكل التي المجاز التي واجهتها محاولة تمثيل كل أقل هياكل البيانات على مستوى المستوى مع تمثيل قياسي واحد مغلقة للبيانات الجدولية. توفر لغة البرمجة ذات الكائن على مستوى رقاقة مثل أوبجكتيف-C معيارا مفتوحا لتمثيل البيانات المنظمة. فهي تسمح للمبرمجين بتطوير بيانات جديدة عن طريق تحديد فئات جديدة من الكائنات، وذلك باستخدام ميزات ذات توجه كائن مثل التغليف والميراث والتعدد. يتم دعم اللغات من قبل أحدث أدوات البرمجة مثل المتصفحات والمكتبات شاملة من جديرة بالثقة، جاهزة للاستخدام، والطبقات التي تم اختبارها مسبقا. وبما أن الأجسام على مستوى الرقاقة هي، بحكم تعريفها، يمكن التعرف على الأشياء التي تم إنشاؤها حديثا على نحو مترابط وقابل للتوصيل ومتعدد الأشكال وديناميكيا من خلال التطبيقات الموجودة مسبقا دون الحاجة إلى إعادة ترجمة التطبيقات أو تعديلها بطريقة أخرى. مثال: تجربة تاسكماستر و أوبجكتيف-C (توك) ستيبستونز مع أوبجكتيف-C هي مثال أخير على السبب في أنه من المستحسن استخدام بنية برامج متعددة المستويات. في حين أن تجربة المجاز تبين أن المبرمجين المهرة يحتاجون إلى معايير معمارية أقل مستوى من الأجسام المستعارة على مستوى بطاقة، تظهر تجربة ستيبستونز أن المستخدمين بحاجة إلى أنواع عالية المستوى من الكائنات من الكائنات النصية، متزامنة من الكائنات أوبجكتيف-C التي التواصل عن طريق إرسال كل الرسائل الأخرى حيث يحسب المستقبل كخيار فرعي للمرسل، بدلا من كوروتين. والمفاهيم الأساسية التي تميز النظم العليا القابلة للبرمجة من لغات البرمجة المتخصصة اليوم، والتي يمثل فيها الهدف-جيم مثالا نموذجيا، هي واجهات المستخدم الأيقونية (بدلا من لغة البرمجة النصية) والمتزامنة (غير المتزامنة، إجرائية) التي تعمل كروتينات لبعضها البعض، وليس عمليات فرعية. لم تتخذ الخطوة، ومن غير المرجح أن تتخذ، والخطوة الأخيرة لبناء أنظمة برمجة المستخدم أنفسنا. ونرى دورنا كموفر للمكونات الأفقية التي سيستخدمها العملاء لبناء حلول المستخدمين النهائيين الرأسية. إيكباك 101 هي مكتبة من الطبقات الأساس التي تميل إلى أن تستخدم في كل تطبيق تقريبا. أكثر الفئات استخداما في هذه المكتبة هي فئة الكائن، والتي هي الفئة الجذر لمعظم التراتيب الهرمية للوظيفة، وظائف الإمدادات لجميع الفئات الأخرى، مثل ستورون: / ريادفروم: آلية تحويل الكائنات تلقائيا (تيارات مرجعية) إلى حرف التمثيل (تيار القيمة) للتخزين أو النقل عبر الشبكات أو الأنابيب. توفر هذه المكتبة أيضا فئات مفيدة عادة بنية البيانات مثل مجموعات، قواميس، صفائف، قوائم، وسلاسل. لا يتم بيع هذه المكتبة بشكل منفصل، ولكن يتم تجميعها مع برنامج التحويل البرمجي. إيكباك 201 هي مكتبة أكبر بكثير من الطبقات لبناء واجهات المستخدم الشهيرة بطريقة منصة مستقلة. قابلية هو أيضا بسبب واجهة أبي / بدل متميزة. على العديد من المنصات، ويستند إيكباك 201s بدل على X - ويندوز، ولكن هذا بدل يمكن أن يكون، وكان، على أساس المكتبات الرسومات الأخرى، بما في ذلك الأجهزة الرسومات عارية. تاسكماستر هي مكتبة من الطبقات لبناء كائنات غير متزامنة على مستوى البطاقة التي تعمل كروتينات من بعضها البعض، وليس عمليات فرعية. وتستند هذه المكتبات إلى الهدف - C، الذي ستيبستون أيضا الأسواق باعتبارها تقنية الربط على مستوى رقاقة ملزمة على نحو فضفاض لتوفير مكتبات فئة كبيرة التي هي فضفاضة إلى حد كبير إلى بيئتهم التي يمكن استخدامها في تطبيقات العملاء المختلفة. أوبجكتيف-C عبارة عن لغة برمجة هجينة موجهة نحو الكائن تدعم نموذج كائن على مستوى رقاقة سمالتالك باعتباره امتدادا متوافقا صعودا صارما إلى كائنات مستوى البوابة والكتلة بلغة برمجة تقليدية مثل C أو C: وسرس أوف ستيبستونيس أوبجكتيف - C، الذي يستند إلى أنسي C، يعبر عن العمليات على مستوى البوابة والكتلة في C. ومن المقرر إصدار يستند إلى C، ولكن ليس متوفرا حاليا. المستخدمين من نكستس الهدف-C مترجم، الذي يقوم على غنو C، تعبر عن العمليات على مستوى البوابة والكتلة في أي C أو C. ستيبستون لا ينظر نفسه على أنه بائع اللغة، على الرغم من واحد من منتجاتنا الأكثر شعبية هو مترجم للغة البرمجة الهدف-C. ونحن ننظر إلى أنفسنا كمورد مكونات البرمجيات، مع لغة كما تمكين التكنولوجيا لمكونات الإلتصاق معا. نحن لا نرى الهدف - C كما تتنافس مع غيرها من لغات البرمجة الشعبية، سواء كانت C، أدا، سمالتالك، C، أو قذيفة يونيكس. الهدف C هو امتداد إلى C. بقدر ما C هو أفضل C، بل هو منصة أفضل من C لبناء أفضل الهدف - C. تاسكماستر الوصف الفني (توك) الكثير للوجهة. بقية هذه الوثيقة هي جولة للسيارة للذهاب إلى هناك، من غرفة إلى غرفة المرجل. وسوف يبين كيف يمكن تجميع أنظمة المستعمل القابلة للبرمجة على مستوى البطاقات من مكونات البرمجيات على مستوى رقاقة من الهدف C، وهذه من تكنولوجيات البوابة والكتلة من C أو C. وبما أن العرض سيكون أضيق تدريجيا وأكثر تقنية من هنا، أولئك الذين غير مهتمين في المسائل غرفة المرجل قد ترغب في إحالة الأجزاء الفنية إلى أخصائي. الهدف تاسكماسترز هو توفير خفيفة الوزن متعددة المهام نموذج الكائن مع انخفاض النفقات العامة بما فيه الكفاية أن المبرمجين لن يتردد في استخدامه على نطاق واسع لأنها تستخدم المكالمات والرواية الفرعية اليوم. وبما أن المهام خفيفة الوزن تشترك في نفس مساحة العنوان، فإنها يمكن أن تتبادل بحرية البيانات المركزة على مؤشر مكثف، مثل الكائنات أوبجكتيف-C. علامة واحدة من هذه الفلسفة العلوية منخفضة هو أن معظم مرافق تاسماسترز يمكن الوصول إليها من خلال زوج من واجهات برمجة التطبيقات. بالإضافة إلى واجهة تمرير الرسائل الناتجة عن تنفيذ تاسكماسترز كمكتب فئة الهدف-C، يتم أيضا تعبئتها كل أساليب الطبقات بحيث يمكن أيضا أن يطلق عليها كروتينات C العادية، مما يسمح للبرامج C العادية لاستدعاء تاسكماسترز وظيفة كاملة في غياب الهدف-ج. وبعبارة أخرى، تاسكماستر ليست محددة للهدف C، ويمكن استخدامها من قبل برامج C العادية. ومع ذلك، لتوضيح ما يلي، سأقوم بوصف تاسكماستر من حيث أبي-أوبجكتيف-C. المهام الخفیفة وتغییر السیاق (توك) البرامج العادیة C (والھدف - C) الافتراضات الخارجیة حول بیئة تنفیذھا بسیطة للغایة. برنامج يجد نفسه تحميلها في مجال الكمبيوتر (مساحة العنوان)، مقسمة إلى أربعة رموز الساحة، البيانات، كومة و كومة الذاكرة المؤقتة. الساحة رمز يحمل رمز البرامج، الساحة البيانات يحمل البرامج بيانات ثابتة، والمكدس و كومة الساحات فارغة في البداية. يشير برنامج برنامج الآلات (بيسي) إلى عنوان بدء البرامج في مجال التعليمات البرمجية ومؤشر كومة (سب) يشير إلى المكدس، الذي هو فارغ في البداية باستثناء وسيطات سطر الأوامر (أرجك، أرجف، وما شابه ذلك). وعادة ما تشارك السجلات الإضافية أيضا، ولكن طالما أنها يتم حفظها واستعادتها بشكل صحيح أثناء تبديل المهام، سيكون من المفيد تجاهلها. وتظهر هذه الحالة الأولية في الشكل 3. ويظهر مجال (ربما واحد من عدة على نظام تقاسم الوقت) بجوار اثنين آخرين. يتم تهيئة كائن المجال مسبقا لاستخدامها ككوادر، وبيانات، وساحات كومة الذاكرة المؤقتة. هذه لا يتم رسمها كمناطق منفصلة لأنها تعتبر أفضل تقسيمها بين الكائنات رسمها على أنها مربعات صغيرة. المكدس الأولي هو المستطيل المدور في الأسفل. The machines registers are shown at the bottom, initialized so that the PC points to the first instruction and the SP points to the first slot of the (empty) stack arena. When TaskMaster is linked into such a program, it is automatically invoked at start up time via Objective-Cs class initialization mechanism. The initialization allocates several TaskMaster objects to formalize the situation as objects. It creates an instance of Domain, theDomain . to model the address space as a whole, and an instance of Task, rootTask . to formalize the root task represented by the initial register settings. The initialization also initializes several global and static variables for its subsequent use, the primary ones being a currentTask variable, initialized to rootTask, and readyQueue . initialized to empty (since no other tasks exist yet). Additional tasks are created when rootTask requests it through any of a variety of ways, differing only in syntactic convenience. What follows will be presented in terms of a uniform syntactic mechanism, Actions . which are modeled after Smalltalks Block mechanism. The Action mechanism will be, but is not yet, supported by the Objective-C compiler. Until it is described later, think of actions as a more powerful, easier to use and understand, replacement for many of the things function pointers are used for in C. The simplest way to create additional tasks (remember, other ways are also provided, including invoking the task creation logic by ordinary C function calls) is to send a fork message to an instance of Action. Actions incorporate a C function that plays the role that main(argc, argv) played for the domain as a whole: aTask anAction fork The message returns a new instance of Task. This involves allocating a stack arena7 for the new task from the heap initialized such that, when the task is executed for the first time, the actions initial C subroutine will find its arguments in the normal fashion for any C subroutine. The newly created task is automatically linked onto the readyQueue for eventual execution. The rootTask might create several such tasks, sending messages and calling functions as it does so, thus modifying the stack space of rootTask. Figure 4 shows rootTasks situation at an arbitrary point in its computation, three levels deep into a subroutine call or message send: Since TaskMaster does not provide preemptive scheduling, rootTask will remain in control until it performs some action that will put it to sleep and let one of the queued tasks proceed. Normally, a task does not do this by explicitly invoking the low-level primitives to be described here. It does so implicitly, by invoking a lightweight I/O operation on one of the I/O channel mechanisms described in the next section. The highest-level kernel entry that a user might access directly is the Semaphore class. Semaphores are a queue on which tasks can to wait for a resource and a count of available resources8. Suppose that some task does a lightweight read operation (anObject aStream get) on a communication channel, such as a stream, whose internal buffer is initially empty. Streams use semaphores to monitor the status of this buffer, so the emptySemaphores resource count variable will indicate that currentTask must wait for another task to add something to the buffer. Therefore, the semaphore will delay the task by linking it onto the semaphores queue of waiting tasks and call taskScheduler to put the current task to sleep and start another one running. The task scheduler chooses the topmost task in the readyQueue9 as nextTask, and calls the context switching routine as follows: contextSwitch(ampcurrentTask-gtregisters, ampnextTask-gtregisters, nextTask) This is where the magic happens. Whereas it was currentTask that called this function, a different task is running when it returns. This new task has its very own execution history (stack area) exactly as it was when the task was last put to sleep by contextSwitch. The magic is quite simple. A lightweight task is simply the machines execution state along with the call history that produced that state. Both are represented by the machines SP register. Calling a subroutine pushes these registers into the address in the SP register, and returning restores them from the address in the same register. The contextSwitch routine accomplishes its magic by saving the current tasks execution state, the SP register, in currentTask-gtregisters and loads another tasks SP from nextTask-gtregisters10. where the new task was saved when it was put to sleep. New tasks are handled the same way by initializing the stack arena and the tasks register save area such that contextSwitch will start the task as if its entry subroutine had been called via an ordinary subroutine call. The size of a tasks stack arena is established when the task is created, either with a reasonable default size or a size specified by the programmer. This arena cannot be enlarged thereafter because of deep-seated assumptions in Cs run-time model that are beyond TaskMasters control. If a task uses more than this amount, perhaps because of unforeseen recursion, the results would be unpredictable. Since providing a more robust subroutine-call mechanism in C is not practical, TaskMaster takes a less drastic approach. It initializes each stack arena with a block of guard information, which taskScheduler checks before every context switch to detect whether the task that has just finished running has overrun its allocation. Lightweight I/O (across tasks) (toc) The previous section showed how TaskMaster supports semaphores within an vanilla C environment, without depending on platform facilities whose absence would lead to non-portability. Semaphores are an extremely low-level scheduling primitive, too powerful for non-specialists in the same way that assembly language is too powerful. Although TaskMaster does provide semaphores, they should be regarded as a low-level mechanism for experts to use in building higher-level mechanisms that are not already available off-the-shelf. TaskMaster applications are concurrent applications (in the restricted sense of the previous section). Concurrently active tasks must be careful to synchronize the tasks access to shared data so that race conditions do not occur. The computer literature is full of ways for doing this, ranging from extremely low-level and general mechanisms like semaphores and event counts at the one extreme, to intermediate-level mechanisms like the Ada rendezvous mechanism at the other, to the ultra-high-level but ultra restrictive pipes and filters mechanism of Unix. The synchronization mechanisms that are most highly developed in TaskMaster today are oriented toward supporting the higher-level of object-oriented granularity that was described earlier as card-level integration libraries of loosely-coupled, iconic, concurrent modules that non-programmers can plug together (at runtime, not compile time) to create custom applications. The higher-level task mechanisms to be described next follow the Unix pipes and filters model, modified to assume lightweight tasks (card-level modules) that communicate by sending chip-level objects through lightweight communication channels such as streams11 . This philosophy departs from other workers in this field. For example, Grady Boochs library of Ada components takes a different approach, in which every reusable object (say, a Collection class), must allow for the fact that it may be accessed concurrently by multiple tasks. In practice, this means that every collection class must exist in multiple versions, one with guard logic to support concurrent access and others that do not for non-shared applications. Card-level objects reflect a different philosophy. Just as hardware cards do not share chips, software card-level objects (tasks) do not share chip-level objects such as collections. Rather, they communicate through specialized communication channel objects such as Streams a software analog for hardware busses between cards. Of course, hardware analogies are seldom perfect in software. As we shall see, the signals that these software buses carry are the same kind of chip-level objects that comprise the cards themselves. Whereas Booch would speak of two tasks sharing a common object, we view them as each owning the object at different times, passing it through a communication channel object that provides whatever sharing paradigm is needed. Streams are the simplest sharing paradigm of all I own it unless I give it to you. Since the stream sharing paradigm is simple to explain and to use, we expect that it will be the prevalent, but never the only, synchronization mechanism in user-programmable systems12. For example, Harrys program (Figure 1) is built entirely of task instances (icons) connected by stream instances (arrows). The large icons are tasks programmed to operate on objects flowing through streams and the small black dots represent generalized stream operations such as fork and join. Each of the tasks in such a system are programmed in a similar fashion, as a loop that reads objects from an incoming stream, processes them, and emits objects on an outgoing stream. For example, here is how a task might be coded in ordinary Objective-C, without using Action expressions: inObject s-gtinStream get process inObject compute outObject. The two streams in this example, inStream and outStream, may have been preallocated by the rootTask and passed to this task as formal parameters as argc and argv are passed to Unix programs. It is also possible to pass such information in global variables (all tasks share the same global address space), or to create them within the task itself. The following larger example creates three tasks that communicate via two streams13. using action expressions to avoid the syntactic clutter that would result had this been written using functions and function pointers: main(int argc, char argv, char envp) Stream stream1 Stream forObjects Stream stream2 Stream forObjects In this example, the rootTask is creating three sub-tasks, which are automatically enrolled them on the readyQueue for eventual execution. When this task executes the currentTask waitForExit. message, it will be suspended14 and the first task on the readyQueue, task1, will begin executing. The Stream forObjects message creates streams that, by default15. support buffered communication. In this respect, streams are similar to the formatted I/O of C stdio functions like fopen(), fread(), printf() and so forth. Stream I/O is buffered I/O, as distinct from the unbuffered I/O of primitives like open(), read(), write(), etc. Since task1s output is buffered, it will loop repeatedly, putting an additional object reference into stream1s internal buffer each time. Eventually the semaphore that stream1 uses to detect a full buffer will determine that task1 must wait. The semaphore will stop the task by linking it onto a queue for consideration once more room becomes available. The next task in the readyQueue (task2) will be scheduled to begin emptying stream1s buffer. And so forth. Heavyweight I/O (across domains) (toc) The preceding section has outlined an architecture in which card-level objects (tasks) communicate by a card-level communication mechanism (streams). And it has showed how card-level objects are constructed from the chip-level mechanisms of Objective-C and these, in turn, from the gate - and block-level mechanisms of C. Now we turn to showing how lightweight tasks couple with the heavyweight processes and I/O mechanisms of a time-sharing operating system, for which Unix is a typical example (Figure 4). Harrys program in Figure 1 contains many examples of where a lightweight task must synchronize with events outside the domain in which the task resides. Three examples are mouse clicks, activity on the modem or the keyboard, and disk I/O. The simplicity that makes Unix so convenient for C and shell programming makes it a worst-case environment for the kind of lightweight tasking extensions described here, far more difficult than environments like VMS or MS/DOS for example. Our success in implementing the TaskMaster PDL within the restrictive Unix environment shows that the TaskMaster API can be implemented on less restrictive platforms like OS/2, MS/DOS, Windows, Mach and other Unix platforms. This section will describe how the TaskMaster API deals with heavy-weight I/O, and then look beneath the covers at how this API was implemented under Sun Unix. The code within a card-level object (a task) should be independent of whether the task happens to be connected to another task, or to an external I/O device, which TaskMaster models as instances of a special class, Port. Whereas streams support a buffered I/O model as in Cs stdio library, ports model unbuffered I/O devices, as in I/O system calls. The logic for filling and emptying a streams buffer depends on whether the stream is connected to a task or to a Port. TaskMaster handles this by providing two stream classes. The Stream class is used only for connecting tasks to tasks. The PortStream class is used for connecting tasks to ports. The two streams offer the same message interface to their clients. By default under Unix, all I/O operations are blocking the whole domain is suspended until I/O is complete. This means that if any task within a domain invokes Unix kernel I/O directly, the kernel will block the domain and every sub-task until the operation has completed. Since this is usually not what is wanted, lightweight tasks avoid doing kernel I/O operations directly by using Streams (for buffered I/O) or Ports (for unbuffered I/O). Streams provide a message protocol that supports all stdio I/O operations, including formatted I/O as in printf(), and ports provide a similar protocol for all kernel I/O operations. Although invoking stdio or kernel I/O directly does no harm apart from the blocking behavior mentioned above, tasks generally use streams or ports for all I/O. Non-blocking I/O is supported by the Port and Sensor classes. The Port class tracks the tasks that have I/O outstanding and schedules them so that other tasks can run while the I/O is pending. It is supported by Sensor, a platform-dependent class in the TaskMaster PDL, whose sole instance, theSensor . provides platform-specific logic for non-blocking I/O. Under Sun Unix, Sensor is based on the Unix select(2) system call. A complication is that streams can carry either references (objects) or values (characters) to other tasks in the same domain, whereas PortStreams can only pass values to Ports. This arises from the fundamental limitation that card-level (lightweight) processes can exchange references (pointers) to chip - and lower-level objects freely, while rack-level (heavyweight) processes can only exchange values (character strings). The PortStream class helps to hide, but of course can never eliminate, the distinction between lightweight and heavyweight I/O16. It implements its reference-stream I/O methods (put: and get) in terms of the storeOn: and readFrom: methods that all objects inherit from the Objective-C root class, Object. The put:method uses storeOn: to represent the argument (and everything it references) as a string of ASCI characters. The get method uses the complementary method, readFrom. to reconstruct the object from this encoding. Exception handling (toc) Consider a subroutine, main(), which calls foo(), which calls bar(). The runtime stack that underlies the C runtime environment extends to record that main has called foo and that foo has called bar. Then it retracts as bar returns to foo and as foo returns to main. The same call/return path is used unconditionally, regardless of whether the subroutines ran successfully or failed because of an exception. The absence of a way of handling exceptions explicitly, independently from normal processing, is a severe obstacle to software quality and reusability. Since subroutines routines return the same way, regardless of whether they succeed or fail, a method that should return a handle to a new object might instead return an error code to indicate that it could not, perhaps because of insufficient memory. Since any such call might fail, the caller must check every return value, reporting any failures to higher levels with similar means. This is sufficiently tedious that it is neglected, allowing unhandled exceptions to crash the application. An exception is a situation where a computation does not proceed as planned, perhaps because of I/O errors, inability to allocate a new object because of insufficient memory, or defects in the software itself. Exception handling is a language/environmental feature that reserves the normal subroutine/message return channel exclusively for normal processing. Routines that return normally can be assumed to have succeeded, since those that fail will return via a independent channel reserved for exceptions. Low-level routines never fail by returning an error code for the caller to decipher, but by raising an exception. Higher level routines establish code fragments, exception handlers, that will receive control if the exception they are to handle is raised by a lower-level routine. The following shows how exception handling might be done in C, in order to show the limitations of this solution and how these limitations are addressed in TaskMaster. TRY() is a C macro that uses setjmp() to record the machines register settings before entering the computation that might fail the foo subroutine. handle low memory exceptions. handle IO failure exceptions.
Comments
Post a Comment