2013-05-16 32 views
7

Thực ra tôi đang sử dụng Visual C++ để cố gắng liên kết các hàm lua như callbacks cho các sự kiện socket (trong một chủ đề khác). Tôi khởi tạo các công cụ lua trong một luồng và socket nằm trong một luồng khác, vì vậy mỗi khi socket gửi/nhận một tin nhắn, nó sẽ gọi hàm lua và hàm lua xác định những gì cần làm theo 'tag' trong thông điệp.Có phải gọi hàm lua (gọi lại) từ một chuỗi khác đủ an toàn không?

Vì vậy, câu hỏi của tôi là:

  1. Kể từ khi tôi vượt qua tình trạng Lua cùng chức năng lua, là an toàn không? Nó không cần bảo vệ gì à? Các hàm lua được gọi từ một thead khác vì vậy tôi đoán chúng có thể được gọi đồng thời.

  2. Nếu không an toàn, giải pháp cho trường hợp này là gì?

Trả lời

2

Không an toàn để gọi lại không đồng bộ vào trạng thái Lua.

Có nhiều cách để giải quyết vấn đề này. Phổ biến nhất liên quan đến một số loại bỏ phiếu.

Một thư viện đồng bộ chung gần đây là DarkSideSync

Một Lua phổ biến ràng buộc để libev là lua-ev

This SO answer khuyến Lanes với LuaSocket Lua.

+0

Bạn có thể giải thích sự khác biệt giữa Luan Lanes và DarkSideSync không? DarkSideSync có ít ví dụ và tôi không biết cách sử dụng DarkSideSync –

+1

Làn đường cung cấp kiểu dữ liệu, Lindas, có thể được chia sẻ an toàn giữa các Lân, trạng thái Lua không đồng bộ. DarkSideSync tập trung hơn vào việc thông báo và liên lạc giữa các thư viện Lua và không đồng bộ. –

+0

Cảm ơn bạn Doug. –

1
  1. Không an toàn khi gọi hàm trong cùng một trạng thái Lua trong nhiều chuỗi.

  2. Tôi đã xử lý cùng một vấn đề, vì trong ứng dụng của tôi tất cả các khái niệm cơ bản như giao tiếp được xử lý bởi C++ và tất cả logic nghiệp vụ được triển khai trong Lua. Những gì tôi làm là tạo ra một hồ bơi của các bang Lua được tạo và khởi tạo trên cơ sở gia tăng (một khi không có đủ trạng thái, tạo một và khởi tạo với các hàm/đối tượng chung). Nó hoạt động như thế này:

    • Khi chuỗi kết nối cần gọi hàm Lua, nó sẽ kiểm tra trường hợp của trạng thái Lua, khởi tạo các hình cầu cụ thể (tôi gọi nó là ngữ cảnh luồng/kết nối) trong một proxy riêng biệt (proxy) bảng toàn cầu ngăn chặn gây ô nhiễm toàn cầu ban đầu, nhưng được lập chỉ mục bởi toàn cầu ban đầu
    • Gọi hàm Lua
    • Kiểm tra trạng thái Lua trở lại hồ bơi, nơi nó được khôi phục trạng thái "sẵn sàng" (vứt bỏ bảng toàn cầu proxy)

Tôi nghĩ cách tiếp cận này cũng phù hợp với trường hợp của bạn. Hồ bơi kiểm tra từng tiểu bang (trên cơ sở khoảng thời gian) khi nó được kiểm tra lần cuối. Khi chênh lệch thời gian đủ lớn, nó sẽ phá hủy trạng thái để bảo toàn tài nguyên và điều chỉnh số trạng thái hoạt động cho tải máy chủ hiện tại. Trạng thái được kiểm tra là trạng thái được sử dụng gần đây nhất trong số các trạng thái có sẵn.

Có một số điều bạn cần phải xem xét khi thực hiện một hồ bơi như:

  • Mỗi tiểu bang cần phải được dân cư với các biến tương tự và chức năng toàn cầu, làm tăng tiêu thụ bộ nhớ.
  • Thực hiện giới hạn trên cho số tiểu bang trong hồ bơi
  • Đảm bảo tất cả các hình cầu ở mỗi trạng thái đều ở trạng thái nhất quán, nếu chúng thay đổi (ở đây tôi khuyên bạn nên chỉ chèn trước các hình cầu tĩnh). ra khỏi một tiểu bang)
  • Nạp năng động. Trong trường hợp của tôi có rất nhiều chức năng/thủ tục có thể được gọi trong Lua. Việc tải chúng liên tục ở tất cả các bang sẽ là một sự lãng phí rất lớn. Vì vậy, thay vào đó tôi giữ cho chúng mã byte được biên dịch ở phía C++ và chúng được nạp khi cần thiết. Hóa ra không ảnh hưởng đến hiệu suất nhiều trong trường hợp của tôi, nhưng số dặm của bạn có thể thay đổi. Một điều cần ghi nhớ là tải chúng chỉ một lần. Giả sử bạn gọi một tập lệnh cần gọi một hàm được nạp động khác trong một vòng lặp. Sau đó, bạn nên tải các chức năng như một địa phương một lần trước khi vòng lặp. Làm như vậy sẽ là một hit hiệu suất rất lớn.

Tất nhiên đây chỉ là một ý tưởng, nhưng một trong số đó hóa ra lại phù hợp nhất với tôi.

+0

Nghe có vẻ hay. Nhưng bất kỳ mã nguồn mở/chia sẻ nếu có thể? –

+0

@MickeyShine - Tôi không thể cung cấp cho bạn bất cứ điều gì đó là realted để Lua, nhưng bạn có thể có một cái nhìn tại 'mysql ++' thực hiện các hồ bơi kết nối, trong đó hoạt động nhiều hơn hoặc ít hơn cách sames. [Hồ bơi kết nối] (http://tangentsoft.net/mysql++/doc/html/refman/classmysqlpp_1_1ConnectionPool.html) –

1
  1. Đó không phải là an toàn, như những người khác đề cập
  2. Phụ thuộc vào usecase của bạn

giải pháp đơn giản nhất là sử dụng một khóa toàn cầu bằng cách sử dụng lua_locklua_unlock macro. Điều đó sẽ sử dụng một trạng thái Lua duy nhất, bị khóa bởi một mutex duy nhất. Đối với một số lượng thấp các callback nó có thể đủ, nhưng đối với lưu lượng truy cập cao hơn nó có thể sẽ không phải do chi phí phát sinh.

Khi bạn cần hiệu suất tốt hơn, hồ bơi nhà nước Lua như được đề cập bởi W.B. là một cách hay để xử lý việc này. Phần khó nhất ở đây tôi tìm thấy đồng bộ hóa dữ liệu toàn cầu trên nhiều tiểu bang.

DarkSideSync, được Doug đề cập, hữu ích trong trường hợp vòng lặp ứng dụng chính nằm ở phía Lua. Tôi đặc biệt viết nó cho mục đích đó. Trong trường hợp của bạn, điều này có vẻ không phù hợp. Có nói rằng; tùy thuộc vào nhu cầu của bạn, bạn có thể xem xét việc thay đổi ứng dụng của bạn để vòng lặp chính không nằm ở phía Lua. Nếu bạn chỉ xử lý ổ cắm, thì bạn có thể sử dụng LuaSocket và không cần đồng bộ hóa. Nhưng rõ ràng là phụ thuộc vào ứng dụng khác.

Các vấn đề liên quan