Khoá hàng đợ

Một phần của tài liệu TỔNG QUAN ĐÁNH GIÁ HIỆU NĂNG MẠNG (Trang 30 - 35)

Một hàng đợi có thể bị khóa hay không ở bất kì thời gian nào. Thông thường, một hàng đợi bị khóa khi một gói tin quá cảnh giữa nó và các dòng tải xuống lân cận nó (phần lớn thời gian nếu hàng đợi bị đầy). Một hàng đợi bị khóa sẽ bị khóa chừng nào liên kết các dòng tải xuống bận và hàng đợi có ít nhất một gói tin được gởi đi. Một hàng đợi được phá khó a chỉ khi hàm cho phép nó tiếp tục được đưa ra (có nghĩa là việc lập trình một dòng tải xuống lân cận nó thông qua việc gọi lại), thường thì khi không có gói tin nào trong hàng đợi. Việc gọi lại được thực thi bằng cách sử dụng các lớp và các phương thức dưới đây:

class QueueHandler : public Handler {

public:

inline QueueHandler(Queue& q) : queue_(q) {} void handle(Event*); /* gọi queue_.resume() */ private: Queue& queue_; }; void QueueHandler::handle(Event*) { queue_.resume(); }

Queue::Queue() : drop_(0), blocked_(0), qh_(*this) {

Tcl& tcl = Tcl::instance(); bind("limit_", &qlim_); }

void Queue::recv(Packet* p, Handler*) { enque(p); if (!blocked_) { p = deque(); if (p != 0) { blocked_ = 1; target_->recv(p, &qh_);

} } } void Queue::resume() { Packet* p = deque(); if (p != 0) target_->recv(p, &qh_); else { if (unblock_on_resume_) blocked_ = 0; else blocked_ = 1; } }

Việc quản lí điều khiển ở đây khôn khéo hơn một chút. Khi một đối tượng Queue mới được tạo ra, nó bao gồm một đối tượng QueueHandler (qh_) được khởi tạo để chứa một tham chiếu tới đối tượng Queue mới (Queue&QueueHandler::queue_). Điều này thực thi bởi Queue đang sử dụng biểu thức qh_(*this). Khi một Queue nhận một gói nó gọi lớp phụ (có nghĩa là hàng đợi đặc tả phương pháp) của hàm enque với gói tin. Nếu hàng đợi không bị khóa, nó cho phép gởi một gói tin và gọi hàm deque xác định gói tin đã gởi, khóa hàng đợi (bởi vì có một gói tin đang quá cảnh), và gởi gói tin tới dòng tải xuống lân cận nó. Chú ý rằng bất cứ gói tin nào nhận được trong tương lai từ dòng tải lên lân cận sẽ đưa đến một hàng đợi bị khóa. Khi một dòng tải xuống yêu cầu nguyên nhân lí do hàng đợi bỏ khóa nó lập trình cho hàm điều khiển của

QueueHandler thông qua qh_ để lập trình mô phỏng. Hàm điều khiển bắt đầu lại, sẽ gởi theo dòng tải xuống gói tin được lập trình tiếp theo (và rời khỏi hàng đợi bị khóa.), hoặc bẻ khóa hàng đợi khi không có gói tin nào sẵn sàng được gởi đi. Việc xử lí này cũng có thể làm gọn gàng hơn với đề nghị của phương thức LinkDelay::recv().

2.6.3. Lớp PacketQueue.

Lớp Queue có thể thực thi việc quản lí bộ đệm và lập trình nhưng không thực thi các hoạt động cấp thấp trên một hàng đợi riêng biệt. Lớp PacketQueue được sử dụng cho mục đích này, và được định nghĩa như sau:

class PacketQueue { public:

PacketQueue();

int length(); /* chiều dài hàng đợi trong các gói tin */

void enque(Packet* p); Packet* deque();

Packet* lookup(int n);

/* Xóa một gói tin đặc biệt trong hàng đợi */ void remove(Packet*);

protected: Packet* head_; Packet** tail_;

int len_; // số gói tin };

Lớp này giữ một danh sách liên kết các gói tin, và thông thường được sử dụng bởi việc lập trình riêng biệt và quản lí bộ đệm để giữ một trật tự thiết lập

các gói tin. Việc lập trình riêng biệt hay sự sắp xếp quản lí hệ thống bộ nhớ có thể sử dụng nhiều đối tượng PacketQueue. Lớp PacketQueue quản lí việc đếm các gói tin hiện tại trong hàng đợi được trả về bằng phương thức length(). Hàm enque đặt gói tin ở cuối hàng đợi và cập nhật lại biến thành viên len_. Hàm deque trả về gói tin ở đầu hàng đợi và xóa nó khỏi hàng đợi (và cập nhật lại biến đếm counter), hay trả về NULL néu hàng đợi rỗng. Hàm lookup trả về gói tin nth ở đầu hàng đợi, hay NULL trong các trường hợp khác. Hàm remove xóa gói tin lưu trữ trong địa chỉ lấy từ hàng đợi (và cập nhật lại biến đếm). Nó tạo ra một chương trình không bình thường và kết thúc nếu gói tin không tồn tại.

Ví dụ : Drop Tail

Ví dụ dưới đây làm sáng tỏ việc thực thi đối tượng Queue/DropTail, thực thi lập trình FIFO và việc quản lí bộ đệm bỏ trên luồng (drop-on-overflow) trong hầu hết các router Internet ngày nay. Định nghĩa dưới đây sẽ trình bày các lớp và kết nối Otcl của nó:

class DropTail : public Queue { protected:

void enque(Packet*); Packet* deque(); PacketQueue q_; };

Lớp cơ sở Queue, DropTail xuất phát từ đó, cung cấp hầu hết các chức năng cần thiết. Hàng đợi drop-tail duy trì chính xác một hàng đợi FIFO, thực thi bởi việc bao gồm một đối tượng của lớp PacketQueue. Drop-tail thực thi chính phiên bản của enque và deque như sau:

void DropTail::enque(Packet* p) {

q_.enque(p); if (q_.length() >= qlim_) { q_.remove(p); drop(p); } } Packet* DropTail::deque() { return (q_.deque()); }

Ở đây, hàm enque đầu tiên lưu trữ gói tin trong hàng đợi các gói tin bên trong (không bị giới hạn), và sau đó kiểm tra kích thước của hàng đợi gói tin thông qua qlim_. Drop-on-overflow được thực thi bằng cách bỏ đi hầu hết các gói tin vừa được thêm vào hàng đợi gói tin nếu đã đạt đến hay vượt qua giới hạn. Việc thực thi trên enque, thiết lập qlim_ lên n trên thực tế có nghĩa là kích thước của hàng đợi là n-1. lập trình FIFO đơn giản được thực thi trên hàm deque bởi việc thường xuyên trả về gói tin đầu tiên trong hàng đợi gói tin.

Một phần của tài liệu TỔNG QUAN ĐÁNH GIÁ HIỆU NĂNG MẠNG (Trang 30 - 35)

Tải bản đầy đủ (PDF)

(75 trang)