Подієво-орієнтоване програмування (англ. event-driven programming; надалі СОП) — парадигма програмування, в якій виконання програми визначається подіями — діями користувача (клавіатура, миша), повідомленнями інших програм і потоків, подіями операційної системи (наприклад, надходженням мережевого пакету).
СОП можна також визначити як спосіб побудови комп'ютерної програми, при якому в коді (як правило, в головній функції програми) явним чином виділяється головний цикл програми, тіло якого складається з двох частин: вибірки події та обробки події.
Як правило, в реальних завданнях виявляється неприпустимим тривале виконання обробника події, оскільки при цьому програма не може реагувати на інші події. У зв'язку з цим при написанні подієво-орієнтованих програм часто застосовують автоматное програмування.
Подійно-орієнтованого програмування, як правило, застосовується в трьох випадках: при побудові користувальницьких інтерфейсів (в тому числі графічних); при створенні серверних додатків в разі, якщо з тих чи інших причин небажано породження обслуговуючих процесів; при програмуванні ігор, в яких здійснюється управління безліччю об'єктів.
Подієво-орієнтоване програмування застосовується в серверних додатках для вирішення проблеми масштабування на 10000 одночасних з'єднань і більше.
В серверах, побудованих за моделлю «один потік на з'єднання», проблеми з масштабністю виникають по наступним причинах: занадто великі накладні витрати на структури даних операційної системи, необхідні для опису однієї задачі (сегмент стану задачі, стек); занадто великі накладні витрати на перемикання контекстів.
Філософської передумовою для відмови від потокової моделі серверів може служити вислів Алана Коксу: «Комп'ютер — це кінцевий автомат. Потокове програмування потрібно тим, хто не вміє програмувати кінцеві автомати»[].
Серверний додаток при подієво-орієнтованому програмуванні реалізується на системному виклику, одержуючому події одночасно від багатьох дескрипторів (мультиплексування). При обробці подій використовуються виключно неблокирующие операції вводу-виводу, щоб ні один дескриптор не перешкоджав обробки подій від інших дескрипторів.
Для мультиплексування сполук можуть бути використані такі засоби операційної системи: select (більшість UNIX-систем). Погано масштабується, з-за того, що список дескрипторів представлений у вигляді бітової карти; poll і epoll (Linux); kqueue (FreeBSD); /dev/poll (Solaris); IO completion port (Windows); POSIX AIO на поточний момент тільки для операцій дискового введення-виведення; io submit і eventfd для операцій дискового введення-виведення.
Веб-сервери: Node.js з nginx або lighttpd Проксі-сервери: Кальмари
У сучасних мовах програмування події і обробники подій є центральною ланкою реалізації графічного інтерфейсу користувача. Розглянемо, наприклад, взаємодія програми з подіями від миші. Натискання правої клавіші миші викликає системне переривання, що запускає певну процедуру всередині операційної системи. У цій процедурі відбувається пошук вікна, що знаходиться під курсором миші. Якщо вікно знайдено, то ця подія надсилається в чергу обробки повідомлень цього вікна. Далі, в залежності від типу вікна, можуть генеруватися додаткові події. Наприклад, якщо вікно є кнопкою миші (Windows всі графічні елементи є вікнами), то додатково генерується подія натискання на кнопку. Відмінність останнього події в тому, що воно більш абстрактно, а саме, не містить координат курсору, а говорить просто про те, що було вироблено натискання на цю кнопку.
Обробник події може виглядати наступним чином (на прикладі C#):
Тут обробник події являє собою процедуру, в яку передається параметр sender, як правило містить вказівник на джерело події. Це дозволяє використовувати одну і ту ж процедуру для обробки подій від декількох кнопок, розрізняючи їх за цим параметром.
У мові C# події реалізовані як елемент мови і є членами класів. Механізм подій тут реалізує шаблон проектування Publisher/Subscriber. Приклад оголошення події:
public class MyClass { public event EventHandler MyEvent; }
Тут EventHandler — делегат, який визначає тип процедури обробника подій. Підписка на подію проводиться наступним чином:
myClass.MyEvent += new EventHandler(Handler);
Тут myClass — екземпляр класу MyClass, Handler — процедура-обробник. Подія може мати необмежену кількість обробників. При додаванні обробника події він додається в спеціальний стек, а при виникненні події викликаються всі обробники за їх порядку в стеку. Відписка від події, тобто видалення обробника проводиться аналогічно, але з використанням оператора «-=».
Різні мови програмування підтримують СОП різною мірою. Найбільш повною підтримкою подій мають такі мови (неповний список): Perl (події і демони DAEMON, і їх пріоритети PRIO),[] Delphi (мова програмування), ActionScript 3.0, C# (події event)[3], JavaScript (дії користувача).
Решта мов, більшої їх частини, підтримують події як обробку виняткових ситуацій.