- •Integer -32768 .. 32767 2 байта
- •Указатели и массивы
- •Xhtml 1.0css 2.1ie 7ie 8ie 9Cr 8Op 12Sa 5Fx 4
- •If (проверка_условия) оператор_1; else оператор_2;
- •100, Тем не менее длина строки и в первом и во втором случаях одна и та же.
- •Internal.
- •Var HeadOfStr: Pointer; ElemOfStr: DynStr;
- •Int main()
- •Int getc(file* fp);
- •Void * func_name(void * arg)
- •Задание графических примитивов
Void * func_name(void * arg)
Чаще всего функция pthread_setcancelstate() используется для временного запрета завершения потока.
. Мы можем оградить этот участок кода от досрочного завершения с помощью пары вызовов pthread_setcancelstate():
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
... //Здесь поток завершать нельзя
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
Создание и запуск потоков
Для создания потоков используется конструктор класса Thread, принимающий в качестве параметра делегат типа ThreadStart, указывающий метод, который нужно выполнить. Делегат ThreadStart определяется так:public delegate void ThreadStart();
Вызов метода Start начинает выполнение потока. Поток продолжается до выхода из исполняемого метода. Вот пример, использующий полный синтаксис C# для создания делегата ThreadStart:class ThreadTest
{
static void Main()
{
Thread t = new Thread(new ThreadStart(Go));
t.Start(); // Выполнить Go() в новом потоке.
Go(); // Одновременно запустить Go() в главном потоке.
}
static void Go() { Console.WriteLine("hello!"); }
В этом примере поток выполняет метод Go() одновременно с главным потоком. Результат – два почти одновременных «hello»:hello!
hello!
Поток можно создать, используя для присваивания значений делегатам более удобный сокращенный синтаксис C#:static void Main()
{
Thread t = new Thread(Go); // Без явного использования ThreadStart
t.Start();
...
}
static void Go() { ... }
В этом случае делегат ThreadStart выводится компилятором автоматически. Другой вариант сокращенного синтаксиса использует анонимный метод для создания потока:static void Main()
{
Thread t = new Thread(delegate() { Console.WriteLine("Hello!"); });
t.Start();
}
Поток имеет свойство IsAlive, возвращающее true после вызова Start() и до завершения потока.
Поток, который закончил исполнение, не может быть начат заново.
Передача данных в ThreadStart
Допустим, что в рассматриваемом выше примере мы захотим более явно различать вывод каждого из потоков, например, по регистру символов. Можно добиться этого, передавая соответствующий флаг в метод Go(), но в этом случае нельзя использовать делегат ThreadStart, так он не принимает аргументов. К счастью, .NET Framework определяет другую версию делегата – ParameterizedThreadStart, которая может принимать один аргумент:public delegate void ParameterizedThreadStart(object obj);
Предыдущий пример можно переписать так:class ThreadTest
{
static void Main()
{
Thread t = new Thread(Go);
t.Start(true); // == Go(true)
Go(false);
}
static void Go(object upperCase)
{
bool upper = (bool)upperCase;
Console.WriteLine(upper ? "HELLO!" : "hello!");
}
}
Консольный вывод:hello!
HELLO!
В этом примере компилятор автоматически выводит делегат ParameterizedThreadStart, так как метод Go() принимает в качестве параметра один object. С тем же успехом можно было написать:Thread t = new Thread(new ParameterizedThreadStart(Go));
t.Start(true);
Особенность использования ParameterizedThreadStart состоит в том, что перед использованием нужно привести аргумент из типа object к нужному типу (в данном случае bool). К тому же существует только версия, принимающая единственный аргумент.
В качестве альтернативы можно использовать анонимный метод:static void Main()
{
Thread t = new Thread(delegate(){ WriteText("Hello"); });
t.Start();
}
static void WriteText(string text) { Console.WriteLine(text); }
Удобство состоит в том, что нужный метод (в данном случае WriteText) можно вызвать с любым количеством аргументов и безо всякого приведения типов. Однако нужно принять во внимание особенность семантики анонимных методов, связанную с внешней переменной, которая становится очевидной в следующем примере:static void Main()
{
string text = "Before";
Thread t = new Thread(delegate() { WriteText(text); });
text = "After";
t.Start();
}
static void WriteText(string text) { Console.WriteLine(text); }
Консольный вывод:After
ПРЕДУПРЕЖДЕНИЕ
Анонимные методы открывают причудливые возможности непреднамеренного взаимодействия через внешние переменные, если они изменяются кем-либо после старта потока. Планового взаимодействия (обычно через поля класса) как правило более чем достаточно! Лучше всего, как только началось исполнение потока, рассматривать внешние переменные как переменные только для чтения – за исключением разве что реализаций с соответствующими блокировками на обеих сторонах.
Другой способ передачи данных в поток состоит в запуске в потоке метода определенного экземпляра объекта, а не статического метода. Тогда свойства выбранного экземпляра объекта будут определять поведение потока, как в следующем варианте оригинального примера:class ThreadTest
{
bool upper;
static void Main()
{
ThreadTest instance1 = new ThreadTest();
instance1.upper = true;
Thread t = new Thread(instance1.Go);
t.Start();
ThreadTest instance2 = new ThreadTest();
instance2.Go(); // Запуск в главном потоке - с upper=false
}
void Go(){ Console.WriteLine(upper ? "HELLO!" : "hello!"); }
Поддержка параллельных вычислений в языке Си++. Возможности и ограничения использования.
Параллельные вычисления — такой способ организации компьютерных вычислений, при котором программы разрабатываются как набор взаимодействующих вычислительных процессов, работающих параллельно (одновременно). Термин охватывает совокупность вопросов параллелизма в программировании, а также создание эффективно действующихаппаратных реализаций. Теория параллельных вычислений составляет раздел прикладной теории алгоритмов.[1]
Существуют различные способы реализации параллельных вычислений. Например, каждый вычислительный процесс может быть реализован в виде процесса операционной системы, либо же вычислительные процессы могут представлять собой набор потоков выполнения внутри одного процесса ОС. Параллельные программы могут физически исполняться либо последовательно на единственном процессоре — перемежая по очереди шаги выполнения каждого вычислительного процесса, либо параллельно — выделяя каждому вычислительному процессу один или несколько процессоров (находящихся рядом или распределённых в компьютерную сеть).
Основная сложность при проектировании параллельных программ — обеспечить правильную последовательность взаимодействий между различными вычислительными процессами, а также координацию ресурсов, разделяемых между процессами.
OpenGL. Назначение. Основные возможности и особенности.
OpenGL является на данный момент одним из самых популярных программных интерфейсов (API) для разработки приложений в области двумерной и трехмерной графики. Стандарт OpenGL был разработан и утвержден в 1992 году ведущими фирмами в области разработки программного обеспечения, а его основой стала библиотека IRIS GL, разработанная Silicon Graphics.
На данный момент реализация OpenGL включает в себя несколько библиотек (описание базовых функций OpenGL, GLU,GLUT,GLAUX и другие), назначение которых будет описано ниже.
Характерными особенностями OpenGL, которые обеспечили распространение и развитие этого графического стандарта, являются:
Стабильность
Дополнения и изменения в стандарте реализуются таким образом, чтобы сохранить совместимость с разработанным ранее программным обеспечением.
Надежность и пеыреносимость
Приложения, использующие OpenGL, гарантируют одинаковый визуальный результат вне зависимости от типа используемой операционной системы и организации отображения информации. Кроме того, эти приложения могут выполняться как на персональных компьютерах, так и на рабочих станциях и суперкомпьютерах.
Легкость применения
Стандарт OpenGL имеет продуманную структуру и интуитивно понятный интерфейс, что позволяет с меньшими затратами создавать эффективные приложения, содержащие меньше строк кода, чем с использованием других графических библиотек. Необходимые функции для обеспечения совместимости с различным оборудованием реализованы на уровне библиотеки и значительно упрощают разработку приложений.
Основные возможности OpenGL
· Набор базовых примитивов: точки, линии, многоугольники и т.п.
· Видовые и координатные преобразования
· Удаление невидимых линий и поверхностей (z-буфер)
· Использование сплайнов для построения линий и поверхностей
· Наложение текстуры и применение освещения
· Добавление специальных эффектов: тумана, изменение прозрачности,сопряжение цветов (blending), устранение ступенчатости (anti-aliasing).
Как уже было сказано, существует реализация OpenGL для разных платформ, для чего было удобно разделить базовые функции графической системы и функции для отображения графической информации и взаимодействия с пользователем. Были созданы библиотеки для отображения информации с помощью оконной подсистемы для операционных систем Windows и Unix (WGL и GLX соответственно), а также библиотеки GLAUX и GLUT, которые используются для создания так называемых консольных приложений.
Библиотека GLAUX уступает по популярности написанной несколько позже библиотеке GLUT, хотя они предоставляют примерно одинаковые возможности. В дальнейшем в данном пособии в качестве основной будет рассматриваться библиотека GLUT, предоставляющая широкий набор средств взаимодействия с пользователем.
В состав библиотеки GLU вошла реализация более сложных функций, таких как набор популярных геометрических примитивов (куб, шар, цилиндр, диск), функции построения сплайнов, реализация дополнительных операций над матрицами и т.п. Все они реализованы через базовые функции OpenGL.
OpenGL. Задание вершин. Использование примитивов. Построение объектов.
Под вершиной понимается точка в трехмерном пространстве, координаты которой можно задавать следующим образом:
void glVertex[2 3 4][s i f d](type coords)
void glVertex[2 3 4][s i f d]v(type *coords)
Координаты точки задаются максимум четырьмя значениями: x, y, z, w, при этом можно указывать два (x,y) или три (x,y,z) значения, а для остальных переменных в этих случаях используются значения по умолчанию: z=0, w=1. Как уже было сказано выше, число в названии команды соответствует числу явно задаваемых значений, а последующий символ – их типу.
Координатные оси расположены так, что точка (0,0) находится в левом нижнем углу экрана, ось x направлена влево, ось y- вверх, а ось z- из экрана. Это расположение осей мировой системы координат, в которой задаются координаты вершин объекта, другие системы координат будут рассмотрены ниже.
Однако чтобы задать какую-нибудь фигуру одних координат вершин недостаточно, и эти вершины надо объединить в одно целое, определив необходимые свойства. Для этого в OpenGL используется понятие примитивов, к которым относятся точки, линии, связанные или замкнутые линии, треугольники и так далее. Задание примитива происходит внутри командных скобок:
void glBegin(GLenum mode)
void glEnd(void)
Параметр mode определяет тип примитива, который задается внутри и может принимать следующие значения:
GL_POINTS каждая вершина задает координаты некоторой точки.
GL_LINES каждая отдельная пара вершин определяет отрезок; если задано нечетное число вершин, то последняя вершина игнорируется.
GL_LINE_STRIP каждая следующая вершина задает отрезок вместе с предыдущей.
GL_LINE_LOOP отличие от предыдущего примитива только в том, что последний отрезок определяется последней и первой вершиной, образуя замкнутую ломаную.
GL_TRIANGLES каждая отдельная тройка вершин определяет треугольник; если задано не кратное трем число вершин, то последние вершины игнорируются.
GL_TRIANGLE_STRIP каждая следующая вершина задает треугольник вместе с двумя предыдущими.
GL_TRIANGLE_FAN треугольники задаются первой и каждой следующей парой вершин (пары не пересекаются).
GL_QUADS каждая отдельная четверка вершин определяет четырехугольник; если задано не кратное четырем число вершин, то последние вершины игнорируются.
GL_QUAD_STRIP четырехугольник с номером n определяется вершинами с номерами 2n-1, 2n, 2n+2, 2n+1.
GL_POLYGON последовательно задаются вершины выпуклого многоугольника.
Для задания текущего цвета вершины используются команды
void glColor[3 4][b s i f](GLtype components)
void glColor[3 4][b s i f]v(GLtype components)
Первые три параметра задают R, G, B компоненты цвета, а последний параметр определяет alpha-компоненту, которая задает уровень прозрачности объекта. Если в названии команды указан тип ‘f’ (float), то значения всех параметров должны принадлежать отрезку [0,1], при этом по умолчанию значение alpha-компоненты устанавливается равным 1.0, что соответствует полной непрозрачности. Если указан тип ‘ub’ (unsigned byte), то значения должны лежать в отрезке [0,255].
Разным вершинам можно назначать различные цвета и тогда будет проводиться линейная интерполяция цветов по поверхности примитива.
Для управления режимом интерполяции цветов используется команда void glShadeModel(GLenummode) вызов которой с параметром GL_SMOOTH включает интерполяцию (установка по умолчанию), а с GL_FLAT отключает.
Например, чтобы нарисовать треугольник с разными цветами в вершинах, достаточно написать:
GLfloat BlueCol[3]={0,0,1};
glBegin(GL_TRIANGLE);
glColor3f(1.0, 0.0, 0.0); //красный
glVertex3f(0.0, 0.0, 0.0);
glColor3ub(0,255,0); //зеленый
glVertex3f(1.0, 0.0, 0.0);
glColor3fv(BlueCol); //синий
glVertex3f(1.0, 1.0, 0.0);
glEnd();
Для задания цвета фона используется команда void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha). Значения должны находиться в отрезке [0,1] и по умолчанию равны нулю. После этого вызов команды void glClear(GLbitfield mask) с параметром GL_COLOR_BUFFER_BIT устанавливает цвет фона во все буфера, доступные для записи цвета (иногда удобно использовать несколько буферов цвета).
Кроме цвета аналогичным образом можно определить нормаль в вершине, используя команды
void glNormal3[b s i f d](type coords)
void glNormal3[b s i f d]v(type coords)
Задаваемый вектор может не иметь единичной длины, но он будет нормироваться автоматически в режиме нормализации, который включается вызовом команды glEnable(GL_NORMALIZE).Команды
void glEnable(GLenum mode)
void glDisable(GLenum mode)
производят включение и отключение того или иного режима работы конвейера OpenGL. Эти команды применяются достаточно часто, и их влияние будет рассматриваться в конкретных случаях.