اینم یه تجربه پراکنده دیگه!

با توجه به شلوغی‌های روز افزون زندگی، دارم سعی میکنم که به حد یک نوشته در ماه برسم. قبلا در مورد cmake نوشتم و حالا خواستم یه مورد دیگه که شاید به درد کسی بخوره رو بنویسم.

ما توی کارهایی که انجام می‌دیم سعی کردیم که ویژگی‌های مختلف نرم‌افزارمون قابل فعال و غیر فعالسازی باشه. هر مشتری هم نیازهای خاص خودش رو داره و یه زیرمجموعه از ویژگی‌ها رو تحویل میگیره. کاری که انجام داده بودیم استفاده از پیش‌پردازندهها برای این کار بود. بدین شکل که هر ویژگی یه پیش پردازنده مخصوص خودش داشت که فعال یا غیر فعال میشد.

این روند فعال و غیر فعال سازی همیشه با مشکلات جدی همراه بود بدین صورت که همکارها به علت زیاد بودن و متغیر بودن ویژگی‌ها برای مشتری‌ها بایستی این فایل رو زیاد تغییر میدادن و این تغییرات زیاد باعث می‌شد که خطای انسانی داشته باشن و یه چیزایی یادشون بره و یا اضافه کامپایل کنند و به مشتری بدن

کاری که ما کردیم این بود که این هدر خاص که همه این تعاریف توش بود رو بجای دستی ساختن به کمک cmake ساختیم به این شکل که

  1. یه متغیر از نوع cached تعریف کردیم که بشه به عنوان پارامتر زمان کامپایل اضافه بشه
  2. بر اساس اون متغیر برای هریک از ویژگی‌ها یک مقدار فعال و غیر فعال تخصیص دادیم
  3. از اون متغیرها استفاده کردیم و فایل اصلی رو ساختیم

نمونه این کار به این شکل هست که توی CMakeLists.txt یه چنین چیزی نوشتیم



		

توی فایل

هم یه چنین چیزی هست



		

و به این شکل این فایل بصورت اتوماتیک ساخته میشه و قابل استفاده است

برای اجرا کردن هم میشه با این دوتا دستور برای مشتری‌های مختلف کامپایل کرد



		

همین!

اینم یه تجربه پراکنده دیگه!

خب توی این پست یه ابزار جایگزین برای build کردن نرم‌افزار‌های c و c++ معرفی کنم به اسم ninja. داستان بوجود اومدنش از این قراره که آقای اوان مارتین که توی گوگل روی توسعه google chrome کار میکرده متوجه میشه روند کامپایل کدهاشون بیش از حد کنده و دست و آستینش رو بالا زدن که یه سیستم سریعتر برای build بنویسه که حاصل شد ninja. پیشنهاد میکنم در اولین گام سیستمتون رو اگه cmake نیست cmake کنید و در گام دوم از ninja استفاده کنید

ویژگی‌های ninja

خب ویژگی‌هایی که من بلدم از این قراره

  • سعی در انجام یک کار بصورت درست
  • سعی در خیلی سریع بودن
  • حداقل محدودیت روی نحوه کامپیال شدن کد و سپردن اونها به ابزارهای سطح بالاتر مانند cmake و gyp
  • تشخیص درست وابستگی‌ها
  • سرعت بر سادگی ارجحیت دارد

نمونه موردی

خب همونطور که قبلا هم گفته بودم نحوه کامپایل کدها منتقل شده بود به cmake و تنها کاری که لازم بود من انجام بدم دستورات زیر بود

برای کدهای ما در یک تست غیر علمی نتیجه‌های حدودی زیر برای ۲ یا ۳ بار اجرا بدست اومد

type make ninja
clean build ۶۰s ۱۳s
rebuild ۱۰s ۰٫۳s

همین!

اینم یه تجربه پراکنده دیگه!

چند شب پیش یکی از دوستان با این سوال به سراغ من اومد:

مشکل اینه که وقتی با malloc یا new یک حافظه تخصیص میدی و با free یا delete حافظه رو برمیگیردونی, اون حافظه شاید بلاک هاش خالی بشه اما توی تسک لیست خالی به عنوان منابع استفاده شده میاره و تا پایان پروسه پاک نمیشه. از دوستانی که آشنایی دارن پیگیری کن ببین جریان چیه. مهمه .

خدا خیرت بده. یه جایی از حافظه نمایی رشد میکه و وقتی خالیش میکنیم (با اینکه از لیست heap سیستم عامل خالی میشه) اما توی لیست پروسه‌ها(مثل نتیجه ps) هنوز به عنوان حافظه استفاده شده هست و حافظه آزاد نمیشه !!!‌ عجیبه . کلی توی اینترنت اینو سوال کردن !!

من که لینوکسم. اما فکر کنم ویندوزم همینه. چون سوالای اینترنت هردوشونه

کلا بخوام سوال رو خلاصه کنم اینجوریه که چرا وقتی حافظه رو به سیستم‌عامل پس میدیم واقعا پس داده نمیشه. من یکم از دانسته‌هام استفاده کردم و یکم هم تحقیقات کردم

پیش‌نیازها

پیش نیازهایی که به نظرم باید بدونیم ایناست:

  • نکته صفر اینکه با توجه به تحقیقات من زیر کلمه کلیدی new از همون malloc استفاده میشه. پس بررسی malloc به تنهایی میتونه جوابی برای ما فراهم کنه.
  • اول اینکه باید بدونیم که وقتی malloc صدا زده میشه چه اتفاقی میفته. کاری که malloc میکنه اینه که heap پروسه رو بهت اختصاص میده. حالا heap توسط سیستم عامل مدیریت میشه و در صورت نیاز به پروسه‌ی شما حافظه بیشتری تخصیص میده.
  • دوم اینکه فضای heap توسط کرنل مدیریت میشه و به اصطلاح نگاشته میشه به یه چیزی به نام Virtual Memory
  • سوم اینکهVirtual Memory نگاشته میشن به چیزی به نام Memory Page که نزدیک به سخت افزار تره
  • چهارم اینکه Memory Page نگاشته میشن بلوک‌های واقعی حافظه. از این مطمئن نیستم اما این نزدکترین لایه به سخت افزاره که من باهاش آشنا هستم.

بررسی مساله

حالا اگه بخوایم مساله رو بررسی کنیم باید به چند‌تا سوال جواب بدیم:

  • اول اینکه malloc چطور عمل میکنه؟ در پیاده‌سازیش ساز و کارش چیه؟
  • دوم اینکه روند افزایش طول Virtual Memory و اضافه شدن Memory Pageها چطوره؟
  • سوم اینکه بعد از پس دادن Memory Pageها سیستم عامل چطور اونها رو از یک پروسه پس میگیره؟

خب جواب سوالا به ترتیب اینا به نظر میرسن:

  • پیاده‌سازی‌های متفاوتی از malloc وجود داره
    • پیاده‌سازی معمولا اون اینطوریه که پس از گرفتن حافظه وقتی free شد معمولا اونها رو به سیستم عامل پس نمیده و نگه میداره که شاید بعدا بخواد دوباره تخصیص بده.
    • دوم اینکه درخواست یک Memory Page جدید توسط دستوراتی مثل mmap و sbrk درخواست یک بلاک بزرگ حافظه میکنه و اون رو بنا به درخواست نرم‌افزار تخصیص میده.
    • بعدش هم اینکه برای اینکه یک Memory Page رو برگردونه به سیستم عامل بایستی تمام حافظه‌هایی که روی اون تخصیص داده شدن برگشت داده بشه. که این هم همیشه اتفاق نمی‌افته.
    • معمولا هم پیاده‌سازی‌ها اینجورین که حافظه‌ای که توسط sbrk افزایش پیدا کرده رو دست نمیزنن(دلیل دقیقش رو نمیدونم) و حافظه‌ای که توسط mmap اضافه شده رو به راحتی برمیگردونن.
  • تقریبا جواب سوال دوم رو هم تا الان دادم. مقدار Virtual Memory توسط glibc کنترل میشه و بوسیله malloc تخصیص داده میشه.
  • جواب سوال سوم هم اینه که کرنل لینوکس همیشه حافظه برگشت داده شده رو برنمیگردونه چون که هزینه داره فقط اون رو علامت میزنه که در صورت نیاز اون رو حذف کنه یا به swap ببره.

راه حل مساله

حالا بریم سراغ مساله اصلی(چرا حافظه برگشت داده شده برگشت نخورده) و توجیهی که براش پیدا کردیم:
* مهمترین دلیل این اتفاق به نظرم malloc هست که حافظه رو نگه داشته و برنگردونده
* دومین دلیلش هم میتونه این باشه که کرنل هنوز Memory Page رو برنداشته و فقط علامت زده

حالا راه حل چیه:
* اول اینکه به کرنل و glibc اعتماد کنیم
* دوم اینکه بیایم و این پارامتر مروبط به malloc رو تنظیم کنیم۴
* سوم اینکه بیایم از یه پیاده‌سازی دیگه برای تخصیص حافظه و آزاد سازی اون استفاده کنیم
* چهارم اینکه بیایم خودمون مستقم از mmap و munmap استفاده کنیم

امیدوارم اینا راه گشای دیگران هم باشه

برای مطالعه بیشتر:

۱

۲

۳

۴

همین!

اینم یه تجربه پراکنده دیگه!

متاسفانه یه مدت میشه که سرم بیش از اندازه شلوغ شده و نرسیدم وبلاگ بنویسم. قبلا در مورد cmake نشوتم و حالا خواستم یکم بیشتر بنویسم.

خب توی این پست سعی میکنم که بگم که توی دنیای واقعی من از cmake چطور میتونم استفاده کنم. توی دنیای واقعی معمولا پروژه از این بخش‌ها تشکیل شده:

  1. یه سری سورس که اصل منطق برنامه اونجا پیاده سازی شده
  2. یه فایل اصلی یا main که تابع اصلی نرم افزار اونجا قرار گرفته
  3. احتمالا یه سری تست که نرم افزار رو بصورت اتوماتیک مورد تست قرار میدن
  4. احتمالا یه سری کتابخانه که بصورت static یا dynamic به کد اضافه میشن.

یه خورده توضیح بدم که توی مcmake معمولا یه چیزی داریم به عنوان خروجی که میتونه از جنس فایل اجرایی باشه یا از جنس کتابخانه. ما با ترکیب کتابخانه‌ها و سورس کدهای موجود فایل اجرایی نهایی رو درست میکنیم. روند کار هم معمولا به این صورته که:
۱٫ سورسهای اصلی بصورت یه کتابخانه static کامپایل میشه
۲٫ فایل اصلی برنامه بصورت یک فایل اجرایی کامپایل شده و به کتابخانه سورس‌های اصلی لینک میشه
۳٫ تست کیسها بصوت یک فایل اجرایی کامپایل شده و به کتابخانه سورس‌هاس اصلی لینک میشه.
۴٫ کتابخانه ها هم به فایل اجرایی اضافه میشن.

حالا اگه مثال بخوایم یه پروژه رو مثال بزنم که ساختار کدش به شکل زیره



		

فایل CMakeLists.txt این پروژه یه چیزی شبیه این خواهد بود



		

شامل یک کتابخانه static و دو فایل اجرایی یکی اصل برنامه و دیگری تست برنامه.

همین!

اینم یه تجربه پراکنده دیگه!

من قبلا هم در مورد ابزارهایی مثل makefile و cmake که کامپیال کردن نرم‌افزارها بالاخص در زبان‌های C/C++ رو راحت می‌کنن نوشتم. البته باید بگم که هیچوقت بصورت کامل و درستی یاد نگرفتم که makefile چطوره و چطور میشه باهاش سرو کله زد تا اینکه در یکی از پروژه‌ها مجبور به استفاده از makefile شدم و با کمک یکی از دوستان یه پروژه متن‌باز پیدا کرد که یه مدل آماده makefile که توش تقریبا همه کارهای معمول انجام شده بود رو آورده بود.

توی این پست سعی درام که این پروژه متن‌باز رو معرفی کنم. خب اول باید بگم که شما برای هر پروژه جدید نیاز دارید که چندتا چیز رو مشخص کنید

  1. اینکه بدونید سورس پروژه کجاست.
  2. اینکه فولدرهایی که header ها توش قرار گرفته کجاست
  3. اینکه بدونید برنامه‌تون به چه کتابخانه‌هایی نیاز داره
  4. اینکه بدونید برنامه‌تون برای کامپیال شدن به کمک GCC به چه flagهایی نیاز داره.

بعد از اینکه این موارد رو دونستید و اونها رو پیدا کردید باید برید و بخشها مرتبط با این موارد رو توی makefile تغییر بدید به عنوان Customizable Section مشخص شده.



		

خب هر یک از این بخش‌های قابل تغییر برای خودش معنایی داره

  1. بخش مقدار flag هایی هست که برای کامپیال کردن فایلها با پسوند c به کار میره. لازه به ذکره که بدونید flagهای C با C++ می‌تونن تفاوت اساسی داشته باشند
  2. بخش نشون‌دهنده flag هایی هست که در فاز link قرار به linker داده بشه و با استفاده از اون کتابخانه ها شناسونده بشن. یه مثال برای این مقدار هست که میگه کتابخانه مورد نیاز این نرم‌افزار هست
  3. بخش بخشی هست که نشون میده flagهای کامپایل c++ چیا هستن. مثلا که نشون میده میخوایم از استاندارد C++ 2011 استفاده کنیم. فولدر headerها رو هم توی این بخش اضافه می‌کنیم
  4. اگه به هر دلیل بخوایم flagهای دیگه ای به linker بدیم از استفاده می‌کنیم.
  5. سورس نرم‌افزار رو با جاهایی که سورس قرار گرفته رو نشون میده.
  6. و در نهایت نام نرم‌افزار رو نشون میده.

امیدوارم با این توضیحات کوتاه دستتون اومده باشه که چه کاری رو به چه صورت باید انجام بدید و در صورت هرگونه سوالی کامنت بگذارید و یادتون نره که من هنوز makefile رو بخوبی بلد نیستم! 😉

اینم یه تجربه پراکنده دیگه!

خب من به مسائل مرتبط با کارایی و اجرای غیر همزمان کدها یا همون async رو دوست دارم. یکم هم تجربه کد نویسی رو باهاشون دارم. توی این پست میخوام بصورت ساده یکی از روشهای این پیاده‌سازی رو براتون توضیح بدم. خیلی دنبال این نیستم که بگم دقیقا این روش کجاها به درد میخوره و چرا به درد میخوره بلکه هدف یه معرفی اولیه است. انشالا در یه پست مفصل بیشتر توضیح میدم. کل موضوع حول دوتا واژه promise و future میگرده که در c++0x11 معرفی شده.

داستان از این قراره که در مدل sync شما یه تابع رو صدا میزنی و منتظر میمونی که جواب به شما برگرده. اما در این مدل بعد از صدا زدن یک تابع بجای منتظر موندن برای جواب همون موقع یک مقدار از نوع future برمیگرده که تا زمانی که تابع صدا زده شده به اتمام نرسیده مقداری نداره. بعد از تموم شدن تابع مقدار future همون مقداری هست که نتیجه محاسباته. حالا اگه از منظر تابعی که صدا زده میشه نگاه کنیم اون تابع خروجیش از نوع promise هست که بعد از اتمام اون رو پر میکنه و برمیگردونه. همین!

حالا این نمونه کد رو هم ببنید که یه مثال ساده از future و promise هست.

مثالها از اینجا گرفته شده. اولین مثال از این قرار که ما یه تابع که خروجیش void هست رو با استفاده future مورد استفاده قرار می‌دیم.



		

اتفاقی که اینجا میفته اینه که با استفاده از ‍

ما سعی میکنیم که اون تابع رو در یک thread دیگه اجرا کنیم و نتیجه رو بصورت یک future از اون بگیریم. با اجرای

مطمئن می‌شیم که اجرای اون thread به اتمام رسیده.

مثال دوم یه محاسبه بصورت غیر همزمان اجرا میشه و نتیجش به کمک future برگردونده میشه



		

امیدوارم که این بدردتون خورده باشه.
همین!

cmake diagram

اینم یه تجربه پراکنده دیگه!

متاسفانه یه مدت میشه که سرم بیش از اندازه شلوغ شده و نرسیدم خوب وبلاگ بنویسم. اما این هفته یه کار خوبی انجام دادم که گفتم اینجا مستندش کنم.

خب همونطور که ممکنه بدونید من توسعه اصلی کارهام در زبان‌های c و c++ هست. یکی از ویژگی‌هایی که این زبان‌ها دارن این هست که شما بایستی برای کامپایل شدن برنامه همیشه از یک IDE استفاده کنی یا از ابزارهایی مثل make برای لینوکس یا مثلا nmake در ویندوز. خب وقتی شما بخوای یه کد رو بین پلتفروم‌های مختلف و برنامه نویس‌های مختلف به اشتراک بگذاری همیشه این سوال وجود داره که دقیقا چطور میشه روند build رو یه جوری از وابستگی به سیستم عامل و حتی پلتفرم آزاد کرد. یه موضوع دیگه‌هم اینه که چطور میشه برای برنامه نویسان این آزادی رو ایجاد کرد که از IDE مورد علاقه‌شون استفاده کنند.

برای جواب به این سوالات و خیلی سوالات دیگه جامعه متن باز پروژه‌ای به نام cmake ایجاد کرده که ویژگی‌های خیلی خوبی داره و همچنین یادگیریش به نسبت آسونه!

ویژگی‌های cmake

خب اگه بگم ویژگی‌های cmake رو بصورت خلاصه بگم اینها هستن

  • امکان کامپایل‌کردن کد بدون در نظر گرفتن محل کد
  • امکان کامپایل‌کردن کد روی سیستم‌عاملهای مختلف
  • امکان تشخیص محل فایل‌ها، کتابخانه‌ها
  • مدیریت وابستگی ها
  • امکان تولید فایل‌های make برای سیستم‌های مختلف و تولید پروژه برای IDEهای مختلف

کاری که من با cmake انجام دادم

کاری که من با کم cmake انجام دادم رو سعی میکنم براتون توضیح بدم. خب ما یه کد داشتیم که برای سه تا پلتفرم سخت افزاری مختلف با سه تا کامپایلر مختلف به سه دسته کتابخانه مختلف کامپایل و لینک میشد. کد تمام این پروژه‌ها یکسان بود اما فقط توسط کامپایلرهای مختلف توی محیط netbeans کامپایل میشد. کاری که انجام دادم این بود:

  • ابتدا پروژه فعلی رو تنها برای یک پلتفرم به cmake تبدیل کردم
    • کامپایلر استاندارد رو به کامپایلر دلخواه تبدیل کردم
    • آدرس کتابخانه‌ها و header فایلهای استاندارد رو عوض کردم
    • بصورت اتوماتیک لیست تمام فایلهای پروژه استخراج میشه
  • با استفاده از پارامترها و ساختار منطقی که cmake ساپورت میکنه دو تا پلتفرم دیگه رو اضافه کردم
    • یه متغیر کنترلی تعریف کردم
    • با استفاده از متغیر کنترلی و if همه موارد بالا رو برای هر پلتفرم تعریف کردم
    • اسم خروجی باینری و فولدر اون رو بر اساس متغیر کنترلی تعیین کردم.

حالا با این حال من تنها یک فایل دارم که باهاش کار سه تا پروژه رو انجام میدم که خب این خیلی جالب و جذابه

همین!

اینم یه تجربه پراکنده دیگه!

یکی از کارهای متفاوتی که من میکنم اینه که توی لینوکس به زبان c++ برنامه نویسی میکنم. معمولا توی برنامه‌هایی هم که مینویسم نیاز داره که با سوکت‌های کار کنم. معمولا هم کارها طوریه که معمولا دسترسی به سوکت مهمه. من گشتم و یه سری کتابخانه برای اینکار پیدا کردم. به نظرم جالب بود که اینلیست این کتابخانه ها رو اینجا بگم.

قبل از معرفی بگم چرا به این دست کتابخانه‌ها نیازه. اولا اگه تجربه کار با سوکت‌ها رو داشته باشید میدونید در مجموع کار کردن با سوکت‌ها سخته. اولا اینکه برای ایجاد یک اتصال نیاز به انجام مقدماتی هست (مثلا تبدیل آی پی به یه قالب خاص یا تبدیل نام سایت به آی پی) همچنین یه سوکت در c++ حالت‌های گوناگونی داره که کار کردن و هندل کردن تمام این حالت‌ها معمولا کار سختیه. نکته بعدی اینه که روند کار با سوکت توی ویندوز، لینوکس و سایر سیستم‌ عامل ها متفاوت و نوشتن یه کد potable کار سخت تریه. پس معقوله شما با دادن یه هزینه معقول در زمینه کارایی و سایز کد نرم‌افزار، سطح بالاتر با سوکت سر و کله بزنی!

لیست این کتابخانه‌های اینا هستن:

  • Boost.Asio: این کتابخانه یه کتاب‌خانه سریع و خوب برای کار با سوکت‌هاست و شما به سوکت بصورت مستقیم دسترسی داری
  • ACE: از دل دانشگاه در اومده و به نظر خوب میاد. سوکت‌ها بصورت مستقیم در دسترس هستند اما عملیات‌های سطح بالاتر مثل message routing رو پشتیبانی میکنه
  • C++ Network Library: تا اونجایی که نمونه‌های و مستنداتش رو بررسی کردم این کتابخانه برای کارهای سطح بالا تر مثل http نوشته شده
  • POCO: این کتابخانه مجموعه ای از ابزارهای سطح بالا برای برنامه نویسی در اختیار شما قرار میده که شبکه و سوکت‌های یکی از اونهاست
  • Qt: این کتابخانه هم مجموعه بسیار بزرگی از ابزارها داره که یکی از اونها شبکه و سوکت هست
  • Raknet: یه کتابخانه کار با شبکه است که هم توی pc و هم توی کنسولهای بازی کاربرد داره
  • ZeroMQ: این کتابخانه بیشتر از اینکه یه کتابخانه شبکه باشه یه کتابخانه message queue هست که به شما کمک میکنه ارتباط بین چندتا اپلیکیشن رو بصورت قابل اعتمادی ایجاد کنید
  • nanomsg: این کتابخانه هم بیشتر به عنوان message queue طراحی شده
  • libevent: اصالتا یه سیستم برای پشتیبانی از سیستم‌های async هست که در جاهای بسیاری استفاده شده و بخشی از اون هم کارهای شبکه و سوکت رو انجام میده
  • Apache APR: یکی دیگر از کتابخانه‌های عموی با پشتیبانی از سوکت است
  • yield: یک کتابخانه نوشتن نرم‌افزارهای تحت وب است
  • wvstreams: یک کتابخانه قدیمی برای کار با شبکه است که سال‌هاست بروزرسانی نشده
  • libcurl: یک کتابخانه بسیار قوی برای کار با پروتکل‌های شبکه نه سوکت‌هاست که بیشتر پروتکل‌های معمول رو پشتیبانی میکنه
  • libuv: یک کتابخانه برای کار با async IO بوده که از شبکه و سوکت هم پشتیبانی میکنه. جالبه بدونید که توی nodejs هم از این کتابخانه استفاده شده.
  • SFML’s Network Module: این کتابخانه هم مثل qt یک کتابخانه چند منظوره است که از سوکت‌ها و شبکه هم پشتیبانی میکنه.

من خودم به شخصه تنها از Boost.Asio استفاده کردم و انشاا… اگه عمری بود بیشتر در مورد این کتابخانه و نمونه کدها و ویژگی‌های دیگشون مینویسم.

همین!

اینم یه تجربه پراکنده کوتاه دیگه!

من اخیرا توی یکی از پروژه‌هام که به زبان c++ نوشته شده نیاز داشتم که از یک شبه ORM به نسبت سبک استفاده کنم چند تا ویژگی داشته باشه. این ویژگی‌ها عبارتند از:

  1. متن باز باشه
  2. وابستگی‌های زیادی نداشته باشه
  3. حداقل از sqlite و mysql و postgres پشتیبانی کنه
  4. استفاده ازش راحت باشه

گزینه‌های زیادی جلوی روم نبود

یادمه نمیاد چرا odb رو از لیست انتخاب‌هام حذف کردم. اما qxrm به دلیل اینکه نمیخواستم یه وابستگی جدید(وابستگی به qt) به کدم اضافه کنم استفاده نکردم. و در انتها از soci استفاده کردم. کار با soci به نسبت راحته و فقط کافیه که نمونه کد ازش ببینید. تقریبا هم توی تمام توزیع‌های لینوکس قابل استفاده است

#include "soci.h"
#include "soci-oracle.h"
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <exception>

using namespace soci;
using namespace std;

bool get_name(string &name)
{
    cout << "Enter name: ";
    return cin >> name;
}

int main()
{
    try
    {
        session sql(oracle, "service=mydb user=john password=secret");

        int count;
        sql << "select count(*) from phonebook", into(count);

        cout << "We have " << count << " entries in the phonebook.\n";

        string name;
        while (get_name(name))
        {
            string phone;
            indicator ind;
            sql << "select phone from phonebook where name = :name",
                into(phone, ind), use(name);

            if (ind == i_ok)
            {
                cout << "The phone number is " << phone << '\n';
            }
            else
            {
                cout << "There is no phone for " << name << '\n';
            }
        }
    }
    catch (exception const &e)
    {
        cerr << "Error: " << e.what() << '\n';
    }
}

همین.

 

اینم یه تجربه پراکنده دیگه!

ایندفعه گفتم یه مطلب کوتاه بنویسم. اگه بخواید توی c++11 که آخرین نسخه زبان c++ هست بصورت اتوماتیک تعداد هسته‌های cpu یا همون تعداد thread ها رو دربیارید فقط کافیه که از کتابخانه‌های استاندارد استفاده کنید. نمونه کد هم به شکل زیر هست:

#include <iostream>
#include <thread>
 
int main() {
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << n << " concurrent threads are supported.\n";
}

واسه اطلاعات بیشتر هم به این لینک مراجعه کنید

همین!